o
    *ήcZ                     @   s(  d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	m
Z
mZmZmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlm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& ddl'm(Z(m)Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1 g dZ2dd Z3G dd de(Z4dd Z5G dd de(Z6dd Z7G d d! d!e(Z8dEd#d$Z9G d%d& d&e(Z:dFd(d)Z;ej<fd*d+Z=G d,d- d-e(Z>dFd.d/Z?G d0d1 d1e(Z@d2d3 ZAG d4d5 d5e(ZBd6d7 ZCG d8d9 d9e(ZDd:d; ZEG d<d= d=e(ZFd>d? ZGG d@dA dAe(ZHdBdC ZIdDS )Gz
Finite Discrete Random Variables - Prebuilt variable types

Contains
========
FiniteRV
DiscreteUniform
Die
Bernoulli
Coin
Binomial
BetaBinomial
Hypergeometric
Rademacher
IdealSoliton
RobustSoliton
    )cacheit)Lambda)IntegerRational)EqGeGtLeLt)S)DummySymbol)sympify)binomial)log)	Piecewise)Or)Contains)Range)IntersectionInterval)beta)SingleFiniteDistributionSingleFinitePSpace)_value_checkDensity	is_random)multiset)
filldedent)FiniteRVDiscreteUniformDie	BernoulliCoinBinomialBetaBinomialHypergeometric
RademacherIdealSolitonRobustSolitonc                 O   sl   t tt|}|| }|ddr|j|  t| |}tdd |D r3ddlm}m	} || ||}|j
S )NcheckTc                 s   s    | ]}t |V  qd S N)r   ).0arg r.   </tmp/pip-target-vg8gfxp4/lib/python/sympy/stats/frv_types.py	<genexpr>=   s    zrv.<locals>.<genexpr>r   )CompoundPSpaceCompoundDistribution)listmapr   popr*   r   anysympy.stats.compound_rvr1   r2   value)nameclsargskwargsdistpspacer1   r2   r.   r.   r/   rv7   s   

r?   c                   @   s8   e Zd Zedd Zdd Zedd Zedd Zd	S )
FiniteDistributionHandmadec                 C   s
   | j d S Nr   )r;   selfr.   r.   r/   dictD      
zFiniteDistributionHandmade.dictc                    s6   t d t t fdd| j D tjdfg  S )Nxc                    s   g | ]\}}|t | fqS r.   )r   )r,   kvrF   r.   r/   
<listcomp>K   s    z2FiniteDistributionHandmade.pmf.<locals>.<listcomp>T)r   r   r   rD   itemsr   ZerorC   rF   r.   rI   r/   pmfH   s   "zFiniteDistributionHandmade.pmfc                 C   s   t | j S r+   )setrD   keysrB   r.   r.   r/   rO   M   s   zFiniteDistributionHandmade.setc                 C   sJ   |   D ]}t|dk|dkfd qt|   }tt|dtjkd d S )Nr      z/Probability at a point must be between 0 and 1.zTotal Probability must be 1.)valuesr   sumr   r   false)densitypvalr.   r.   r/   r*   Q   s   z FiniteDistributionHandmade.checkN)	__name__
__module____qualname__propertyrD   rN   rO   staticmethodr*   r.   r.   r.   r/   r@   B   s    

r@   c                 K   s$   | dd|d< t| t|fi |S )a  
    Create a Finite Random Variable given a dict representing the density.

    Parameters
    ==========

    name : Symbol
        Represents name of the random variable.
    density : dict
        Dictionary containing the pdf of finite distribution
    check : bool
        If True, it will check whether the given density
        integrates to 1 over the given set. If False, it
        will not perform this check. Default is False.

    Examples
    ========

    >>> from sympy.stats import FiniteRV, P, E

    >>> density = {0: .1, 1: .2, 2: .3, 3: .4}
    >>> X = FiniteRV('X', density)

    >>> E(X)
    2.00000000000000
    >>> P(X >= 2)
    0.700000000000000

    Returns
    =======

    RandomSymbol

    r*   F)r5   r?   r@   )r9   rU   r<   r.   r.   r/   r   Y   s   $r   c                   @   sH   e Zd Zedd Zedd Zeedd Zedd Z	d	d
 Z
dS )DiscreteUniformDistributionc                  G   s^   t t| t | kr-t| }tt | }|D ]
}||  |  < qttddd|f  d S )Nz
                Repeated args detected but set expected. For a
                distribution having different weights for each
                item use the following:z
S("FiniteRV(%s, %s)")z'X')lenrO   r   r   
ValueErrorr   )r;   weightsnrG   r.   r.   r/   r*      s   
z!DiscreteUniformDistribution.checkc                 C   s   t dt| jS NrQ   )r   r^   r;   rB   r.   r.   r/   rV      s   zDiscreteUniformDistribution.pc                    s    fdd j D S )Nc                    s   i | ]}| j qS r.   )rV   r,   rG   rB   r.   r/   
<dictcomp>   s    z4DiscreteUniformDistribution.dict.<locals>.<dictcomp>)rO   rB   r.   rB   r/   rD      s   z DiscreteUniformDistribution.dictc                 C   s
   t | jS r+   )rO   r;   rB   r.   r.   r/   rO      rE   zDiscreteUniformDistribution.setc                 C   s   || j v r| jS tjS r+   )r;   rV   r   rL   rM   r.   r.   r/   rN      s   
zDiscreteUniformDistribution.pmfN)rX   rY   rZ   r\   r*   r[   rV   r   rD   rO   rN   r.   r.   r.   r/   r]      s    


r]   c                 C   s   t | tg|R  S )aE  
    Create a Finite Random Variable representing a uniform distribution over
    the input set.

    Parameters
    ==========

    items : list/tuple
        Items over which Uniform distribution is to be made

    Examples
    ========

    >>> from sympy.stats import DiscreteUniform, density
    >>> from sympy import symbols

    >>> X = DiscreteUniform('X', symbols('a b c')) # equally likely over a, b, c
    >>> density(X).dict
    {a: 1/3, b: 1/3, c: 1/3}

    >>> Y = DiscreteUniform('Y', list(range(5))) # distribution over a range
    >>> density(Y).dict
    {0: 1/5, 1: 1/5, 2: 1/5, 3: 1/5, 4: 1/5}

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Discrete_uniform_distribution
    .. [2] http://mathworld.wolfram.com/DiscreteUniformDistribution.html

    )r?   r]   )r9   rK   r.   r.   r/   r       s   %r    c                   @   T   e Zd Z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S )DieDistributionsidesc                 C   s   t | j| jfd d S )Nz+number of sides must be a positive integer.)r   is_positive
is_integerrg   r.   r.   r/   r*         zDieDistribution.checkc                 C   
   | j j S r+   )rh   	is_numberrB   r.   r.   r/   is_symbolic   rE   zDieDistribution.is_symbolicc                 C      | j S r+   rg   rB   r.   r.   r/   high      zDieDistribution.highc                 C      t jS r+   r   OnerB   r.   r.   r/   low   rq   zDieDistribution.lowc                 C   s8   | j rttjtd| jS tttt	t
d| jd S Nr   rQ   )rn   r   r   	Naturals0r   rh   rO   r4   r   r3   rangerB   r.   r.   r/   rO         zDieDistribution.setc                 C   sj   t |}|js|jst|stdt| t|dt|| j@ t	|t
j@ }tt
j| j |ft
jdfS NP'x' expected as an argument of type 'number', 'Symbol', or 'RandomSymbol' not %srQ   T)r   rm   	is_Symbolr   r_   typer   r	   rh   r   r   Integersr   rt   rL   )rC   rF   condr.   r.   r/   rN      s   "zDieDistribution.pmfNrX   rY   rZ   	_argnamesr\   r*   r[   rn   rp   ru   rO   rN   r.   r.   r.   r/   rf      s    




rf      c                 C      t | t|S )a  
    Create a Finite Random Variable representing a fair die.

    Parameters
    ==========

    sides : Integer
        Represents the number of sides of the Die, by default is 6

    Examples
    ========

    >>> from sympy.stats import Die, density
    >>> from sympy import Symbol

    >>> D6 = Die('D6', 6) # Six sided Die
    >>> density(D6).dict
    {1: 1/6, 2: 1/6, 3: 1/6, 4: 1/6, 5: 1/6, 6: 1/6}

    >>> D4 = Die('D4', 4) # Four sided Die
    >>> density(D4).dict
    {1: 1/4, 2: 1/4, 3: 1/4, 4: 1/4}

    >>> n = Symbol('n', positive=True, integer=True)
    >>> Dn = Die('Dn', n) # n sided Die
    >>> density(Dn).dict
    Density(DieDistribution(n))
    >>> density(Dn).dict.subs(n, 4).doit()
    {1: 1/4, 2: 1/4, 3: 1/4, 4: 1/4}

    Returns
    =======

    RandomSymbol
    )r?   rf   )r9   rh   r.   r.   r/   r!      s   %r!   c                   @   s0   e Zd ZdZedd Zedd Zdd ZdS )	BernoulliDistributionrV   succfailc                 C   s   t | dk| dkfd d S )Nr   rQ   p should be in range [0, 1].)r   r   r.   r.   r/   r*     s   zBernoulliDistribution.checkc                 C   s   | j | jhS r+   )r   r   rB   r.   r.   r/   rO     s   zBernoulliDistribution.setc                 C   sx   t | jtr#t | jtr#t| j|| jkfd| j || jkftjdfS t| jt|| jfd| j t|| jftjdfS )NrQ   T)	
isinstancer   r   r   r   rV   r   rL   r   rM   r.   r.   r/   rN   #  s   zBernoulliDistribution.pmfN)	rX   rY   rZ   r   r\   r*   r[   rO   rN   r.   r.   r.   r/   r     s    

r   rQ   c                 C      t | t|||S )ay  
    Create a Finite Random Variable representing a Bernoulli process.

    Parameters
    ==========

    p : Rational number between 0 and 1
       Represents probability of success
    succ : Integer/symbol/string
       Represents event of success
    fail : Integer/symbol/string
       Represents event of failure

    Examples
    ========

    >>> from sympy.stats import Bernoulli, density
    >>> from sympy import S

    >>> X = Bernoulli('X', S(3)/4) # 1-0 Bernoulli variable, probability = 3/4
    >>> density(X).dict
    {0: 1/4, 1: 3/4}

    >>> X = Bernoulli('X', S.Half, 'Heads', 'Tails') # A fair coin toss
    >>> density(X).dict
    {Heads: 1/2, Tails: 1/2}

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Bernoulli_distribution
    .. [2] http://mathworld.wolfram.com/BernoulliDistribution.html

    r?   r   )r9   rV   r   r   r.   r.   r/   r"   -  s   )r"   c                 C   s   t | t|ddS )a  
    Create a Finite Random Variable representing a Coin toss.

    Parameters
    ==========

    p : Rational Numeber between 0 and 1
      Represents probability of getting "Heads", by default is Half

    Examples
    ========

    >>> from sympy.stats import Coin, density
    >>> from sympy import Rational

    >>> C = Coin('C') # A fair coin toss
    >>> density(C).dict
    {H: 1/2, T: 1/2}

    >>> C2 = Coin('C2', Rational(3, 5)) # An unfair coin
    >>> density(C2).dict
    {H: 3/5, T: 2/5}

    Returns
    =======

    RandomSymbol

    See Also
    ========

    sympy.stats.Binomial

    References
    ==========

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

    HTr   )r9   rV   r.   r.   r/   r#   Y  s   (r#   c                   @   sd   e Zd Z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eedd ZdS )BinomialDistributionra   rV   r   r   c                 C   s,   t | j| jfd t |dk|dkfd d S )Nz 'n' must be nonnegative integer.rQ   r   r   )r   rj   is_nonnegativer   r.   r.   r/   r*     s   zBinomialDistribution.checkc                 C   ro   r+   ra   rB   r.   r.   r/   rp     rq   zBinomialDistribution.highc                 C   rr   r+   r   rL   rB   r.   r.   r/   ru     rq   zBinomialDistribution.lowc                 C   rl   r+   ra   rm   rB   r.   r.   r/   rn     rE   z BinomialDistribution.is_symbolicc                 C   s(   | j rttjtd| jS t| j S rA   )	rn   r   r   rw   r   ra   rO   rD   rP   rB   r.   r.   r/   rO     s   zBinomialDistribution.setc                 C   s   | j | j}}t|}|js|jst|stdt| t|dt	||@ t
|tj@ }tt||||  d| ||   |ftjdfS )Nr{   r   rQ   T)ra   rV   r   rm   r|   r   r_   r}   r   r	   r   r   r~   r   r   rL   )rC   rF   ra   rV   r   r.   r.   r/   rN     s    2zBinomialDistribution.pmfc                    s,    j rt S  fddtd jd D S )Nc                    s.   i | ]}| j   j|  j   |qS r.   )r   ra   r   rN   rc   rB   r.   r/   rd     s    &z-BinomialDistribution.dict.<locals>.<dictcomp>r   rQ   )rn   r   rx   ra   rB   r.   rB   r/   rD     s
   
zBinomialDistribution.dictN)rX   rY   rZ   r   r\   r*   r[   rp   ru   rn   rO   rN   r   rD   r.   r.   r.   r/   r     s     




	r   c                 C   s   t | t||||S )a  
    Create a Finite Random Variable representing a binomial distribution.

    Parameters
    ==========

    n : Positive Integer
      Represents number of trials
    p : Rational Number between 0 and 1
      Represents probability of success
    succ : Integer/symbol/string
      Represents event of success, by default is 1
    fail : Integer/symbol/string
      Represents event of failure, by default is 0

    Examples
    ========

    >>> from sympy.stats import Binomial, density
    >>> from sympy import S, Symbol

    >>> X = Binomial('X', 4, S.Half) # Four "coin flips"
    >>> density(X).dict
    {0: 1/16, 1: 1/4, 2: 3/8, 3: 1/4, 4: 1/16}

    >>> n = Symbol('n', positive=True, integer=True)
    >>> p = Symbol('p', positive=True)
    >>> X = Binomial('X', n, S.Half) # n "coin flips"
    >>> density(X).dict
    Density(BinomialDistribution(n, 1/2, 1, 0))
    >>> density(X).dict.subs(n, 4).doit()
    {0: 1/16, 1: 1/4, 2: 3/8, 3: 1/4, 4: 1/16}

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Binomial_distribution
    .. [2] http://mathworld.wolfram.com/BinomialDistribution.html

    )r?   r   )r9   ra   rV   r   r   r.   r.   r/   r$     s   /r$   c                   @   re   )BetaBinomialDistributionra   alphar   c                 C   sJ   t | j| jfdt|   t |dkdt|  t |dkdt|  d S )N('n' must be nonnegative integer. n = %s.r   z''alpha' must be: alpha > 0 . alpha = %sz$'beta' must be: beta > 0 . beta = %sr   rj   r   strr   r.   r.   r/   r*     s   


zBetaBinomialDistribution.checkc                 C   ro   r+   r   rB   r.   r.   r/   rp     rq   zBetaBinomialDistribution.highc                 C   rr   r+   r   rB   r.   r.   r/   ru     rq   zBetaBinomialDistribution.lowc                 C   rl   r+   r   rB   r.   r.   r/   rn     rE   z$BetaBinomialDistribution.is_symbolicc                 C   s8   | j rttjtd| jS tttt	t
d| jd S rv   )rn   r   r   rw   r   ra   rO   r4   r   r3   rx   rB   r.   r.   r/   rO     ry   zBetaBinomialDistribution.setc                 C   s@   | j | j| j}}}t||t|| || |  t|| S r+   )ra   r   r   r   beta_fn)rC   rG   ra   abr.   r.   r/   rN        *zBetaBinomialDistribution.pmfN)rX   rY   rZ   r   r\   r*   r[   rp   ru   rn   rO   rN   r.   r.   r.   r/   r     s    




r   c                 C   r   )a~  
    Create a Finite Random Variable representing a Beta-binomial distribution.

    Parameters
    ==========

    n : Positive Integer
      Represents number of trials
    alpha : Real positive number
    beta : Real positive number

    Examples
    ========

    >>> from sympy.stats import BetaBinomial, density

    >>> X = BetaBinomial('X', 2, 1, 1)
    >>> density(X).dict
    {0: 1/3, 1: 2*beta(2, 2), 2: 1/3}

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Beta-binomial_distribution
    .. [2] http://mathworld.wolfram.com/BetaBinomialDistribution.html

    )r?   r   )r9   ra   r   r   r.   r.   r/   r%   	  s   "r%   c                   @   re   )HypergeometricDistribution)Nmra   c                 C   sR   t |j|jfdt|   t | j| jfdt|   t |j|jfdt|   d S )Nz('N' must be nonnegative integer. N = %s.r   z('m' must be nonnegative integer. m = %s.r   )ra   r   r   r.   r.   r/   r*   1  s   


z HypergeometricDistribution.checkc                 C   s    t dd | j| j| jfD  S )Nc                 s   s    | ]}|j V  qd S r+   )rm   )r,   rF   r.   r.   r/   r0   <  s    z9HypergeometricDistribution.is_symbolic.<locals>.<genexpr>)allr   r   ra   rB   r.   r.   r/   rn   :      z&HypergeometricDistribution.is_symbolicc                 C   s$   t | jt| j| jdkf| jdfS )NFT)r   ra   r
   r   rB   r.   r.   r/   rp   >  s   $zHypergeometricDistribution.highc                 C   s8   t dtd| j| j | j dkf| j| j | j dfS )Nr   FT)r   r   ra   r   r   rB   r.   r.   r/   ru   B  s   8zHypergeometricDistribution.lowc                 C   s^   | j | j| j}}}| jrttjt| j| j	S dd t
td|| | t||d D S )Nc                 S   s   h | ]}|qS r.   r.   r,   ir.   r.   r/   	<setcomp>K  s    z1HypergeometricDistribution.set.<locals>.<setcomp>r   rQ   )r   r   ra   rn   r   r   rw   r   ru   rp   rx   maxmin)rC   r   r   ra   r.   r.   r/   rO   F  s   ,zHypergeometricDistribution.setc                 C   s@   | j | j| j}}}tt||t|| ||  t|| S r+   )r   r   ra   r   r   )rC   rG   r   r   ra   r.   r.   r/   rN   M  r   zHypergeometricDistribution.pmfNr   r.   r.   r.   r/   r   .  s    




r   c                 C   r   )a  
    Create a Finite Random Variable representing a hypergeometric distribution.

    Parameters
    ==========

    N : Positive Integer
      Represents finite population of size N.
    m : Positive Integer
      Represents number of trials with required feature.
    n : Positive Integer
      Represents numbers of draws.


    Examples
    ========

    >>> from sympy.stats import Hypergeometric, density

    >>> X = Hypergeometric('X', 10, 5, 3) # 10 marbles, 5 white (success), 3 draws
    >>> density(X).dict
    {0: 1/12, 1: 5/12, 2: 5/12, 3: 1/12}

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Hypergeometric_distribution
    .. [2] http://mathworld.wolfram.com/HypergeometricDistribution.html

    )r?   r   )r9   r   r   ra   r.   r.   r/   r&   R  s   $r&   c                   @   s$   e Zd Zedd Zedd ZdS )RademacherDistributionc                 C   s   ddhS )NrQ   r.   rB   r.   r.   r/   rO   {  s   zRademacherDistribution.setc              	   C   s6   t d}t|ttjtt|dt|dftjdfS )NrG   r   rQ   T)r   r   r   r   Halfr   r   rL   )rC   rG   r.   r.   r/   rN     s   .zRademacherDistribution.pmfN)rX   rY   rZ   r[   rO   rN   r.   r.   r.   r/   r   y  s
    
r   c                 C   s
   t | tS )a  
    Create a Finite Random Variable representing a Rademacher distribution.

    Examples
    ========

    >>> from sympy.stats import Rademacher, density

    >>> X = Rademacher('X')
    >>> density(X).dict
    {-1: 1/2, 1: 1/2}

    Returns
    =======

    RandomSymbol

    See Also
    ========

    sympy.stats.Bernoulli

    References
    ==========

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

    )r?   r   )r9   r.   r.   r/   r'     s   
r'   c                   @   sX   e Zd ZdZedd Zedd Zedd Zedd	 Z	ee
d
d Zdd ZdS )IdealSolitonDistributionrG   c                 C   s   t | jo| jd d S )Nz'k' must be a positive integer.)r   rj   ri   r   r.   r.   r/   r*     rk   zIdealSolitonDistribution.checkc                 C   rr   r+   rs   rB   r.   r.   r/   ru     rq   zIdealSolitonDistribution.lowc                 C   ro   r+   r   rB   r.   r.   r/   rp     rq   zIdealSolitonDistribution.highc                 C      t ttd| jd S rb   rO   r3   r   rG   rB   r.   r.   r/   rO        zIdealSolitonDistribution.setc                 C   sH   | j jrt| S dtd| j i}|tdd td| j d D  |S )NrQ   c                 s   s&    | ]}|t d ||d   fV  qdS )rQ   N)r   r   r.   r.   r/   r0     s   $ z0IdealSolitonDistribution.dict.<locals>.<genexpr>   )rG   r|   r   r   updaterD   rx   )rC   dr.   r.   r/   rD     s
   $zIdealSolitonDistribution.dictc                 C   s   t |}|js|jst|stdt| t|d|j@ }t|dt	|| j
@ |j@ }td| j
 |fd||d   |ftjdfS rz   )r   rm   r|   r   r_   r}   r   rj   r   r	   rG   r   r   rL   )rC   rF   cond1cond2r.   r.   r/   rN     s   ,zIdealSolitonDistribution.pmfN)rX   rY   rZ   r   r\   r*   r[   ru   rp   rO   r   rD   rN   r.   r.   r.   r/   r     s    



r   c                 C   r   )aE  
    Create a Finite Random Variable of Ideal Soliton Distribution

    Parameters
    ==========

    k : Positive Integer
        Represents the number of input symbols in an LT (Luby Transform) code.

    Examples
    ========

    >>> from sympy.stats import IdealSoliton, density, P, E
    >>> sol = IdealSoliton('sol', 5)
    >>> density(sol).dict
    {1: 1/5, 2: 1/2, 3: 1/6, 4: 1/12, 5: 1/20}
    >>> density(sol).set
    {1, 2, 3, 4, 5}

    >>> from sympy import Symbol
    >>> k = Symbol('k', positive=True, integer=True)
    >>> sol = IdealSoliton('sol', k)
    >>> density(sol).dict
    Density(IdealSolitonDistribution(k))
    >>> density(sol).dict.subs(k, 10).doit()
    {1: 1/10, 2: 1/2, 3: 1/6, 4: 1/12, 5: 1/20, 6: 1/30, 7: 1/42, 8: 1/56, 9: 1/72, 10: 1/90}

    >>> E(sol.subs(k, 10))
    7381/2520

    >>> P(sol.subs(k, 4) > 2)
    1/4

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Soliton_distribution#Ideal_distribution
    .. [2] http://pages.cs.wisc.edu/~suman/courses/740/papers/luby02lt.pdf

    )r?   r   )r9   rG   r.   r.   r/   r(     s   .r(   c                   @   sl   e Zd ZdZedd Ze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S )RobustSolitonDistributionrG   deltacc                 C   s<   t | jo| jd t t|dot|dd t |jd d S )Nz'k' must be a positive integerr   rQ   z3'delta' must be a real number in the interval (0,1)z#'c' must be a positive real number.)r   rj   ri   r   r	   r   r.   r.   r/   r*     s   zRobustSolitonDistribution.checkc                 C   s    | j t| j| j  | jd  S )Ng      ?)r   r   rG   r   rB   r.   r.   r/   R  r   zRobustSolitonDistribution.Rc                 C   sT   d}t dt| j| j D ]}|d| 7 }q|t| j| j 7 }d|| j | j  S rv   )r   roundrG   r   r   r   )rC   zr   r.   r.   r/   Z	  s
   zRobustSolitonDistribution.Zc                 C   rr   r+   rs   rB   r.   r.   r/   ru     rq   zRobustSolitonDistribution.lowc                 C   ro   r+   r   rB   r.   r.   r/   rp     rq   zRobustSolitonDistribution.highc                 C   r   rb   r   rB   r.   r.   r/   rO     r   zRobustSolitonDistribution.setc                 C   s   | j jo| jjo| jj S r+   )rG   rm   r   r   rB   r.   r.   r/   rn     s   z%RobustSolitonDistribution.is_symbolicc                 C   s  t |}|js|jst|stdt| t|d|j@ }t|dt	|| j
@ |j@ }ttd| j
|ftd||d  |ftjdf}t|dt	|t| j
| j d @ }t|t| j
| j }t| j| j
|  |f| jt| j| j  | j
 |ftjdf}|| | j S rz   )r   rm   r|   r   r_   r}   r   rj   r   r	   rG   r   r   r   rL   r   r   r   r   r   )rC   rF   r   r   rhotaur.   r.   r/   rN   !  s   0$>zRobustSolitonDistribution.pmfN)rX   rY   rZ   r   r\   r*   r[   r   r   ru   rp   rO   rn   rN   r.   r.   r.   r/   r     s"    






r   c                 C   r   )a  
    Create a Finite Random Variable of Robust Soliton Distribution

    Parameters
    ==========

    k : Positive Integer
        Represents the number of input symbols in an LT (Luby Transform) code.
    delta : Positive Rational Number
            Represents the failure probability. Must be in the interval (0,1).
    c : Positive Rational Number
        Constant of proportionality. Values close to 1 are recommended

    Examples
    ========

    >>> from sympy.stats import RobustSoliton, density, P, E
    >>> robSol = RobustSoliton('robSol', 5, 0.5, 0.01)
    >>> density(robSol).dict
    {1: 0.204253668152708, 2: 0.490631107897393, 3: 0.165210624506162, 4: 0.0834387731899302, 5: 0.0505633404760675}
    >>> density(robSol).set
    {1, 2, 3, 4, 5}

    >>> from sympy import Symbol
    >>> k = Symbol('k', positive=True, integer=True)
    >>> c = Symbol('c', positive=True)
    >>> robSol = RobustSoliton('robSol', k, 0.5, c)
    >>> density(robSol).dict
    Density(RobustSolitonDistribution(k, 0.5, c))
    >>> density(robSol).dict.subs(k, 10).subs(c, 0.03).doit()
    {1: 0.116641095387194, 2: 0.467045731687165, 3: 0.159984123349381, 4: 0.0821431680681869, 5: 0.0505765646770100,
    6: 0.0345781523420719, 7: 0.0253132820710503, 8: 0.0194459129233227, 9: 0.0154831166726115, 10: 0.0126733075238887}

    >>> E(robSol.subs(k, 10).subs(c, 0.05))
    2.91358846104106

    >>> P(robSol.subs(k, 4).subs(c, 0.1) > 2)
    0.243650614389834

    Returns
    =======

    RandomSymbol

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Soliton_distribution#Robust_distribution
    .. [2] http://www.inference.org.uk/mackay/itprnn/ps/588.596.pdf
    .. [3] http://pages.cs.wisc.edu/~suman/courses/740/papers/luby02lt.pdf

    )r?   r   )r9   rG   r   r   r.   r.   r/   r)   1  s   5r)   N)r   )rQ   r   )J__doc__sympy.core.cacher   sympy.core.functionr   sympy.core.numbersr   r   sympy.core.relationalr   r   r   r	   r
   sympy.core.singletonr   sympy.core.symbolr   r   sympy.core.sympifyr   (sympy.functions.combinatorial.factorialsr   &sympy.functions.elementary.exponentialr   $sympy.functions.elementary.piecewiser   sympy.logic.boolalgr   sympy.sets.containsr   sympy.sets.fancysetsr   sympy.sets.setsr   r   &sympy.functions.special.beta_functionsr   r   sympy.stats.frvr   r   sympy.stats.rvr   r   r   sympy.utilities.iterablesr   sympy.utilities.miscr   __all__r?   r@   r   r]   r    rf   r!   r   r"   r   r#   r   r$   r   r%   r   r&   r   r'   r   r(   r   r)   r.   r.   r.   r/   <module>   sV    '%(
"(
,+
.4#%$'&08