<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Symbulate Documentation
Common Discrete Distributions
Introduction to discrete distributions and random variables
Defining a general discrete distribution with BoxModel
Discrete Uniform
Bernoulli
Binomial
Hypergeometric
Poisson
Geometric
Negative Binomial (and the related Pascal)
< Cards, coins, dice | Contents | Common continuous distributions >
Be sure to import Symbulate using the following commands.
Step1:  <a id='discrete'></a>
Introduction to discrete distributions and random variables
<a id='pmf'></a>
A discrete probability distribution assigns positive probability to the values in some countable set.  A discrete distribution can be specified by a probability mass function (pmf), $p(\cdot)$, which maps a value $x$ to its probability $p(x)\in [0,1]$.  A probability mass function must satisfy $\sum_x p(x) = 1$.
A discrete random variable $X$ defined on a probability space with probability measure $P$ has a probability mass function $p_X$ defined by $p_X(x) = P(X = x)$.  The expected value of a discrete random variable is
$$
E(X) = \sum_x x\, p_X(x) = \sum_x x P(X=x)
$$
<a id='boxmodel'></a>
Defining a general discrete distribution with BoxModel
A discrete distribution can be specified via a BoxModel where the tickets represent possible values (i.e. the values with non-zero probability) and the probs option specifies the probabilities.
Example. A certain probability mass function $p$ satisfies $p(1) = 0.4$, $p(2) = 0.2$, $p(5) = 0.3$, $p(10)=0.1$, and $p(x)=0$ otherwise.
Step2:  <a id='discrete_unif'></a>
Discrete Uniform
A discrete Uniform distribution with parameters $a$ and $b$, DiscreteUniform(a, b), assigns equal probability to each integer between $a$ and $b$ (inclusive), as specified by the probability mass function
$$
p(x) = \frac{1}{b - a + 1}, \qquad x \in {a, a+1, \ldots, b-1, b}
$$
If $X$ is a random variable with a DiscreteUniform(a, b) distribution then
$$
\begin{align}
E(X) & = \frac{a + b + 1}{2} \
Var(X) & = \frac{(a + b)^2 - 1}{12}
\end{align}
$$
Example. Actual and simulated pmf for DiscreteUniform(a=1, b=6).
Step3:  Example. DiscreteUniform(a = 1, b) pmf.
Step4:  <a id='bernoulli'></a>
Bernoulli distributions
A Bernoulli($p$) distribution takes value 1 with probability $p$ and 0 with probability $1-p$.
If $X$ is a random variable with a Bernoulli($p$) distribution then
$$
\begin{align}
E(X) & = p \
Var(X) & = p(1-p)
\end{align}
$$
Example. Simulated pmf for Bernoulli(p=0.3).
Step5:  <a id='binomial'></a>
Binomial distributions
Binomial distributions are often used to model the number of successes observed in a fixed number (n) of Bernoulli(p) trials (independent, success/failure trials, with probability of success p on each trial). A Binomial distribution with parameters n (a nonnegative integer) and p (in [0,1]) is specified by the probability mass function
$$
\binom{n}{x} p^x (1-p)^{n-x}, \qquad x = 0, 1, 2, \ldots, n
$$
If $X$ is a random variable with a Binomial($n, p$) distribution then
$$
\begin{align}
E(X) & = np \
Var(X) & = np(1-p)
\end{align}
$$
Example. Actual and simulated pmf for Binomial(n=10, p=0.4).
Step6:  Example. Binomial(n=10, p) pmf.
Step7:  Example. Binomial(n, p=0.4) pmf.
Step8:  <a id='hyper'></a>
Hypergeometric distributions
Hypergeometric distributions are used to model the number of "successes" in n (a nonnegative integer) draws without replacement from a box containing $N_0$ failures and $N_1$ successes. A hypergeometric distribution is specified by the probability mass function
$$
\frac{\binom{N_1}{x}\binom{N_0}{n-x}}{\binom{N_0 + N_1}{n}}, \quad x = 0,1, \ldots, n;\; x \le N_1;\; n-x \le N_0
$$
If $X$ is a random variable with a Hypergeometric($n,  N_0, N_1$) distribution then
$$
\begin{align}
E(X) & = \frac{n N_1}{N_0 + N_1} \
Var(X) & = \frac{n N_1(N_0)(N_0 + N_1 - n)}{(N_0 + N_1)^2(N_0 + N_1 - 1)}
\end{align}
$$
Example. Actual and simulated pmf for Hypergeometric(n=5, N0=5, N1=10).
Step9:  Example. Hypergeometric(n=10, N0=10, N1) pmf.
Step10:  Example. Hypergeometric(n=10, N0, N1= 10) pmf.
Step11:  <a id='poisson'></a>
Poisson distributions
A Poisson distribution with parameter $\lambda>0$ is specified by the probability mass function
$$
\frac{e^{-\lambda} \lambda^x}{x!}, \quad x = 0, 1, 2, \ldots
$$
If $X$ is a random variable with a Poisson($\lambda$) distribution then
$$
\begin{align}
E(X) & = \lambda \
Var(X) & = \lambda
\end{align}
$$
Example. Actual and simulated pmf for Poisson(lam=5).
Step12:  Example. Poisson($\lambda$) pmf.
Step13:  <a id='geometric'></a>
Geometric distributions
Geometric distributions are often used to model the number of Bernoulli($p$) (independent, success/failure) trials needed to achieve the first success.  A geometric distribution with parameter p (in [0,1]) is specified by the probability mass function
$$
p(1-p)^{x-1}, \quad x = 1, 2, 3,\ldots 
$$
If $X$ is a random variable with a Geometric(p) distribution then
$$
\begin{align}
E(X) & = \frac{1}{p} \
Var(X) & = \frac{(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for Geometric(p=0.4).
Step14:  Example. Geometric(p) pmf.
Step15:  <a id='negative_binomial'></a>
Negative binomial distributions
Negative binomial distributions are often used to model the number of Bernoulli($p$) (independent, success/failure) trials needed to achieve a specified number of successes ($r$).  A negative binomial distribution with parameters $p$ and $r$ is specified by the probability mass function
$$
\binom{x-1}{r-1}p^r(1-p)^{x-r}, \quad x = r, r+1, r+2,\ldots 
$$
If $X$ is a random variable with a NegativeBinomial($r, p$) distribution then
$$
\begin{align}
E(X) & = \frac{r}{p} \
Var(X) & = \frac{r(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for NegativeBinomial(r=3, p=0.4).
Step16:  Example. NegativeBinomial(r, p=0.5) pmf.
Step17:  Example. NegativeBinomial(r=5, p) pmf.
Step18:  <a id='pascal'></a>
Pascal distributions
A Pascal distribution has the same shape as a negative binomial distribution, but the distribution is supported on ${0, 1, 2, \ldots}$ rather than ${r, r+1, r+2, \ldots}$ with the probability mass function
$$
\binom{x+r-1}{r-1}p^r(1-p)^{x}, \quad x = 0, 1, 2,\ldots 
$$
If Bernoulli($p$) trials are performed until $r$ successes are achieved, then the number of failures observed will have a Pascal distribution.
If $X$ is a random variable with a Pascal($r, p$) distribution then
$$
\begin{align}
E(X) & = \frac{r(1 - p)}{p} \
Var(X) & = \frac{r(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for Pascal(r=3, p=0.4).
Step19:  Example. Pascal(r, p=0.5) pmf.
Step20:  Example. Pascal(r=5, p) pmf.
<ASSISTANT_TASK:>
Python Code:
from symbulate import *
%matplotlib inline
Explanation: Symbulate Documentation
Common Discrete Distributions
Introduction to discrete distributions and random variables
Defining a general discrete distribution with BoxModel
Discrete Uniform
Bernoulli
Binomial
Hypergeometric
Poisson
Geometric
Negative Binomial (and the related Pascal)
< Cards, coins, dice | Contents | Common continuous distributions >
Be sure to import Symbulate using the following commands.
End of explanation
P = BoxModel([1, 2, 5, 10], probs=[0.4, 0.2, 0.3, 0.1])
P.sim(10000).tabulate(normalize=True)
RV(P).sim(10000).plot()
Explanation: <a id='discrete'></a>
Introduction to discrete distributions and random variables
<a id='pmf'></a>
A discrete probability distribution assigns positive probability to the values in some countable set.  A discrete distribution can be specified by a probability mass function (pmf), $p(\cdot)$, which maps a value $x$ to its probability $p(x)\in [0,1]$.  A probability mass function must satisfy $\sum_x p(x) = 1$.
A discrete random variable $X$ defined on a probability space with probability measure $P$ has a probability mass function $p_X$ defined by $p_X(x) = P(X = x)$.  The expected value of a discrete random variable is
$$
E(X) = \sum_x x\, p_X(x) = \sum_x x P(X=x)
$$
<a id='boxmodel'></a>
Defining a general discrete distribution with BoxModel
A discrete distribution can be specified via a BoxModel where the tickets represent possible values (i.e. the values with non-zero probability) and the probs option specifies the probabilities.
Example. A certain probability mass function $p$ satisfies $p(1) = 0.4$, $p(2) = 0.2$, $p(5) = 0.3$, $p(10)=0.1$, and $p(x)=0$ otherwise.
End of explanation
sims = RV(DiscreteUniform(a=1, b=6)).sim(10000)
sims.plot()
DiscreteUniform(a=1, b=6).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(DiscreteUniform(a=1, b=6).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(DiscreteUniform(a=1, b=6).var()))
Explanation: <a id='discrete_unif'></a>
Discrete Uniform
A discrete Uniform distribution with parameters $a$ and $b$, DiscreteUniform(a, b), assigns equal probability to each integer between $a$ and $b$ (inclusive), as specified by the probability mass function
$$
p(x) = \frac{1}{b - a + 1}, \qquad x \in {a, a+1, \ldots, b-1, b}
$$
If $X$ is a random variable with a DiscreteUniform(a, b) distribution then
$$
\begin{align}
E(X) & = \frac{a + b + 1}{2} \
Var(X) & = \frac{(a + b)^2 - 1}{12}
\end{align}
$$
Example. Actual and simulated pmf for DiscreteUniform(a=1, b=6).
End of explanation
bs = [3, 5, 7]
for b in bs:
    DiscreteUniform(a=1, b=b).plot()
    
plt.legend(["b=" + str(i) for i in bs])
plt.title("Discrete Uniform distributions with a=1")
Explanation: Example. DiscreteUniform(a = 1, b) pmf.
End of explanation
RV(Bernoulli(0.3)).sim(10000).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Bernoulli(0.3).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Bernoulli(0.3).var()))
Explanation: <a id='bernoulli'></a>
Bernoulli distributions
A Bernoulli($p$) distribution takes value 1 with probability $p$ and 0 with probability $1-p$.
If $X$ is a random variable with a Bernoulli($p$) distribution then
$$
\begin{align}
E(X) & = p \
Var(X) & = p(1-p)
\end{align}
$$
Example. Simulated pmf for Bernoulli(p=0.3).
End of explanation
sims = RV(Binomial(10, 0.4)).sim(10000)
sims.plot()
Binomial(10, 0.4).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Binomial(10, 0.4).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Binomial(10, 0.4).var()))
Explanation: <a id='binomial'></a>
Binomial distributions
Binomial distributions are often used to model the number of successes observed in a fixed number (n) of Bernoulli(p) trials (independent, success/failure trials, with probability of success p on each trial). A Binomial distribution with parameters n (a nonnegative integer) and p (in [0,1]) is specified by the probability mass function
$$
\binom{n}{x} p^x (1-p)^{n-x}, \qquad x = 0, 1, 2, \ldots, n
$$
If $X$ is a random variable with a Binomial($n, p$) distribution then
$$
\begin{align}
E(X) & = np \
Var(X) & = np(1-p)
\end{align}
$$
Example. Actual and simulated pmf for Binomial(n=10, p=0.4).
End of explanation
ps = [0.10, 0.50, 0.75]
for p in ps:
    Binomial(10, p).plot()
plt.legend(["p=" + str(i) for i in ps])
plt.title("Binomial distributions with n=10")
Explanation: Example. Binomial(n=10, p) pmf.
End of explanation
ns = [5, 10, 15]
for n in ns:
    Binomial(n, 0.4).plot()
plt.legend(["n=" + str(i) for i in ns])
plt.title("Binomial distributions with p=0.4")
Explanation: Example. Binomial(n, p=0.4) pmf.
End of explanation
sims = RV(Hypergeometric(n=5, N0=5, N1=10)).sim(10000)
sims.plot()
Hypergeometric(n=5, N0=5, N1=10).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Hypergeometric(n=5, N0=5, N1=10).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Hypergeometric(n=5, N0=5, N1=10).var()))
Explanation: <a id='hyper'></a>
Hypergeometric distributions
Hypergeometric distributions are used to model the number of "successes" in n (a nonnegative integer) draws without replacement from a box containing $N_0$ failures and $N_1$ successes. A hypergeometric distribution is specified by the probability mass function
$$
\frac{\binom{N_1}{x}\binom{N_0}{n-x}}{\binom{N_0 + N_1}{n}}, \quad x = 0,1, \ldots, n;\; x \le N_1;\; n-x \le N_0
$$
If $X$ is a random variable with a Hypergeometric($n,  N_0, N_1$) distribution then
$$
\begin{align}
E(X) & = \frac{n N_1}{N_0 + N_1} \
Var(X) & = \frac{n N_1(N_0)(N_0 + N_1 - n)}{(N_0 + N_1)^2(N_0 + N_1 - 1)}
\end{align}
$$
Example. Actual and simulated pmf for Hypergeometric(n=5, N0=5, N1=10).
End of explanation
N1s = [5, 15, 25]
for N1 in N1s:
    Hypergeometric(10, 10, N1).plot()
plt.legend(["N1=" + str(i) for i in N1s])
plt.title("Hypergeometric distributions with N0=10, n=10")
Explanation: Example. Hypergeometric(n=10, N0=10, N1) pmf.
End of explanation
N0s = [5, 15, 25]
for N0 in N0s:
    Hypergeometric(10, N0, 10).plot()
plt.legend(["N0=" + str(i) for i in N0s])
plt.title("Hypergeometric distributions with N1=10, n=10")
Explanation: Example. Hypergeometric(n=10, N0, N1= 10) pmf.
End of explanation
sims = RV(Poisson(lam = 5)).sim(10000)
sims.plot()
Poisson(lam = 5).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Poisson(lam=5).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Poisson(lam=5).var()))
Explanation: <a id='poisson'></a>
Poisson distributions
A Poisson distribution with parameter $\lambda>0$ is specified by the probability mass function
$$
\frac{e^{-\lambda} \lambda^x}{x!}, \quad x = 0, 1, 2, \ldots
$$
If $X$ is a random variable with a Poisson($\lambda$) distribution then
$$
\begin{align}
E(X) & = \lambda \
Var(X) & = \lambda
\end{align}
$$
Example. Actual and simulated pmf for Poisson(lam=5).
End of explanation
lams = [5, 10, 15]
for lam in lams:
    Poisson(lam).plot()
plt.legend(["lambda=" + str(i) for i in lams])
plt.title("Poisson distributions with parameter lambda")
Explanation: Example. Poisson($\lambda$) pmf.
End of explanation
sims = RV(Geometric(p=0.4)).sim(10000)
sims.plot()
Geometric(p=0.4).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Geometric(p=0.4).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Geometric(p=0.4).var()))
Explanation: <a id='geometric'></a>
Geometric distributions
Geometric distributions are often used to model the number of Bernoulli($p$) (independent, success/failure) trials needed to achieve the first success.  A geometric distribution with parameter p (in [0,1]) is specified by the probability mass function
$$
p(1-p)^{x-1}, \quad x = 1, 2, 3,\ldots 
$$
If $X$ is a random variable with a Geometric(p) distribution then
$$
\begin{align}
E(X) & = \frac{1}{p} \
Var(X) & = \frac{(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for Geometric(p=0.4).
End of explanation
ps = [0.25, 0.50, 0.75]
for p in ps:
    Geometric(p).plot()
plt.legend(["p=" + str(i) for i in ps])
plt.title("Geometric distributions with parameter p")
Explanation: Example. Geometric(p) pmf.
End of explanation
sims = RV(NegativeBinomial(r=3, p=0.4)).sim(10000)
sims.plot()
NegativeBinomial(r=3, p=0.4).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(NegativeBinomial(r=3, p=0.4).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(NegativeBinomial(r=3, p=0.4).var()))
Explanation: <a id='negative_binomial'></a>
Negative binomial distributions
Negative binomial distributions are often used to model the number of Bernoulli($p$) (independent, success/failure) trials needed to achieve a specified number of successes ($r$).  A negative binomial distribution with parameters $p$ and $r$ is specified by the probability mass function
$$
\binom{x-1}{r-1}p^r(1-p)^{x-r}, \quad x = r, r+1, r+2,\ldots 
$$
If $X$ is a random variable with a NegativeBinomial($r, p$) distribution then
$$
\begin{align}
E(X) & = \frac{r}{p} \
Var(X) & = \frac{r(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for NegativeBinomial(r=3, p=0.4).
End of explanation
rs = [5, 10, 15]
for r in rs:
    NegativeBinomial(r, p=0.5).plot()
plt.legend(["r=" + str(i) for i in rs])
plt.title("Negative Binomial distributions with p=0.5")
Explanation: Example. NegativeBinomial(r, p=0.5) pmf.
End of explanation
ps = [0.25, 0.50, 0.75]
for p in ps:
    NegativeBinomial(r=5, p=p).plot()
plt.legend(["p=" + str(i) for i in ps])
plt.title("Negative Binomial distributions with r=5")
Explanation: Example. NegativeBinomial(r=5, p) pmf.
End of explanation
sims = RV(Pascal(r=3, p=0.4)).sim(10000)
sims.plot()
Pascal(r = 3, p = 0.4).plot()
print('The simulated mean is: {:.2f}'.format(sims.mean()))
print('The true mean is: {:.2f}'.format(Pascal(r=3, p=0.4).mean()))
print('The simulated variance is: {:.2f}'.format(sims.var()))
print('The true variance is: {:.2f}'.format(Pascal(r=3, p=0.4).var()))
Explanation: <a id='pascal'></a>
Pascal distributions
A Pascal distribution has the same shape as a negative binomial distribution, but the distribution is supported on ${0, 1, 2, \ldots}$ rather than ${r, r+1, r+2, \ldots}$ with the probability mass function
$$
\binom{x+r-1}{r-1}p^r(1-p)^{x}, \quad x = 0, 1, 2,\ldots 
$$
If Bernoulli($p$) trials are performed until $r$ successes are achieved, then the number of failures observed will have a Pascal distribution.
If $X$ is a random variable with a Pascal($r, p$) distribution then
$$
\begin{align}
E(X) & = \frac{r(1 - p)}{p} \
Var(X) & = \frac{r(1 - p)}{p^2}
\end{align}
$$
Example. Actual and simulated pmf for Pascal(r=3, p=0.4).
End of explanation
rs = [5, 10, 15]
for r in rs:
    Pascal(r, p=0.5).plot()
plt.legend(["r=" + str(i) for i in rs])
plt.title("Pascal distributions with p=0.5")
Explanation: Example. Pascal(r, p=0.5) pmf.
End of explanation
ps = [0.25, 0.50, 0.75]
for p in ps:
    Pascal(r=5, p=p).plot()
plt.legend(["p=" + str(i) for i in ps])
plt.title("Pascal distributions with r=0.5")
Explanation: Example. Pascal(r=5, p) pmf.
End of explanation
<END_TASK>