{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5d24fc75",
   "metadata": {},
   "outputs": [],
   "source": [
    "# General used libriries\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy.stats import binom, poisson, norm, expon "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f8545a0",
   "metadata": {},
   "source": [
    "# Bernoulli distribution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "38c1af9c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P(X=1) =  0.7\n",
      "P(X=0) =  0.30000000000000004\n",
      "Mean =  0.7\n",
      "Variance =  0.21000000000000002\n"
     ]
    }
   ],
   "source": [
    "# Bernoulli distribution:\n",
    "p = 0.7\n",
    "print(\"P(X=1) = \", p)\n",
    "print(\"P(X=0) = \", 1-p)\n",
    "print(\"Mean = \", p)\n",
    "print(\"Variance = \", p*(1-p))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2ab9219a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First 20 observations:\n",
      "[1 1 1 1 0 1 1 0 1 1 0 1 1 1 1 0 0 1 1 1]\n",
      "Sample mean:  0.675\n",
      "Sample variance:  0.21959459459459454\n"
     ]
    }
   ],
   "source": [
    "# Bernoulli observations \n",
    "# repeating a success|failures experiment many times\n",
    "p = 0.7\n",
    "n = 1000 #samples\n",
    "np.random.seed(33)\n",
    "berData = np.random.binomial(1, p, size=n)\n",
    "print(\"First 20 observations:\")\n",
    "print(berData[:20])\n",
    "\n",
    "print(\"Sample mean: \", berData.mean())\n",
    "print(\"Sample variance: \", berData.var(ddof=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e2ae2434",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18968 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "values, counts = np.unique(berData, return_counts=True)\n",
    "plt.bar(values, counts/n, width=0.4, color=\"grey\")\n",
    "plt.xticks([0, 1])\n",
    "plt.xlabel(\"Outcomes\")\n",
    "plt.ylabel(\"Relative frequency\")\n",
    "plt.title(\"Simulated Bernoulli Distribution\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98f319fd",
   "metadata": {},
   "source": [
    "# Binomial distribution\n",
    "The binomial distribution counts the number of successes in $n$ independent Bernoulli trials."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "974eccf3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P(X=2) = 0.2711\n",
      "Mean=  1.6\n",
      "Variance=  1.4720000000000002\n"
     ]
    }
   ],
   "source": [
    "p = 0.08\n",
    "n = 20\n",
    "k = 2\n",
    "\n",
    "prob = binom.pmf(k, n, p)\n",
    "print(f\"P(X=2) = {prob:.4f}\")\n",
    "print(\"Mean= \", n*p)\n",
    "print(\"Variance= \", n*p*(1-p))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "87d14367",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20916 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(0, n+1)\n",
    "pmf = binom.pmf(x, n, p)\n",
    "plt.bar(x, pmf, color=\"grey\", width=0.6)\n",
    "plt.xlabel(\"Number of succeses\")\n",
    "plt.ylabel(\"Probability\")\n",
    "plt.title(\"Binomial distribution: n=20, p=0.08\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9c8de1d2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Simulated mean:  1.6011\n",
      "Theoretical mean:  1.6\n",
      "--------------\n",
      "Simulated var:  1.4717259625962598\n",
      "Theoretical var:  1.4720000000000002\n"
     ]
    }
   ],
   "source": [
    "# Binomial simuation\n",
    "n = 20 #sample\n",
    "p = 0.08\n",
    "nPop = 10_000\n",
    "np.random.seed(33)\n",
    "binomData = np.random.binomial(n,p,size=nPop)\n",
    "\n",
    "print(\"Simulated mean: \", binomData.mean())\n",
    "print(\"Theoretical mean: \", n*p)\n",
    "print(\"--------------\")\n",
    "print(\"Simulated var: \", binomData.var(ddof=1))\n",
    "print(\"Theoretical var: \", n*p*(1-p))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "ec289f08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 13060 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(binomData, bins=np.arange(-0.5,n+1.5,1), density=True, color=\"grey\")\n",
    "plt.plot(x, pmf, 'ok')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5ce9af51",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.88693329e-01 3.28162312e-01 2.71090605e-01 1.41438577e-01\n",
      " 5.22707783e-02 1.45449122e-02 3.16193744e-03 5.49902164e-04\n",
      " 7.77035666e-05 9.00910917e-06 8.61740877e-07 6.81218085e-08\n",
      " 4.44272664e-09 2.37737880e-10 1.03364296e-11 3.59527985e-13\n",
      " 9.76978221e-15 1.99893242e-16 2.89700351e-18 2.65171946e-20\n",
      " 1.15292150e-22]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.32816231158747255"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(pmf)\n",
    "20*0.08*(1-0.08)**(19)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2612a6fd",
   "metadata": {},
   "source": [
    "# Poisson distribution\n",
    "- $P(X=k) = e^{-\\lambda} \\lambda^k/k!$\n",
    "- $E[X] = \\lambda$\n",
    "- $Var(X) = \\lambda$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e94cffe1",
   "metadata": {},
   "source": [
    "Example: Let $X$ be the number of flaws per metre per cable, with average rate $\\lambda=3$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c629df8b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P(X=0) =  0.049787068367863944\n",
      "P(X=2) =  0.22404180765538775\n",
      "Mean =  3\n",
      "Var =  3\n"
     ]
    }
   ],
   "source": [
    "lam = 3\n",
    "print(\"P(X=0) = \", poisson.pmf(0, lam))\n",
    "print(\"P(X=2) = \", poisson.pmf(2, lam))\n",
    "print(\"Mean = \", lam)\n",
    "print(\"Var = \", lam)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e8882be4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 16124 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.arange(0, 15)\n",
    "pmfPoisson = poisson.pmf(x, lam)\n",
    "\n",
    "plt.bar(x, pmfPoisson, width=0.7)\n",
    "plt.xlabel(\"Count\")\n",
    "plt.ylabel(\"Probability\")\n",
    "plt.title(r\"Poisson distribution: $\\lambda=3$\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "dd34877c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Simulated mean:  2.9953\n",
      "Theoretical mean:  3\n",
      "Simulated Var:  2.9753754475447542\n",
      "Theoretical Var:  3\n"
     ]
    }
   ],
   "source": [
    "# Poisson distribution\n",
    "lam = 3\n",
    "samples = 10_000\n",
    "poiData = np.random.poisson(lam, size=samples)\n",
    "\n",
    "print(\"Simulated mean: \", poiData.mean())\n",
    "print(\"Theoretical mean: \", lam)\n",
    "\n",
    "print(\"Simulated Var: \", poiData.var(ddof=1))\n",
    "print(\"Theoretical Var: \", lam)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "abcf172f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 23020 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(poiData, bins=np.arange(-0.5, 15.5,1), density=True)\n",
    "plt.plot(x, poisson.pmf(x, lam),'or')\n",
    "plt.xlabel(\"Counts\")\n",
    "plt.ylabel(\"Relative Freq/Probability\")\n",
    "plt.title(\"Poisson: Simulated vs Theory\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb795b6e",
   "metadata": {},
   "source": [
    "# Normal distribution\n",
    "If $X\\sim N(\\mu, \\sigma^2)$, then:\n",
    "- $\\mu$ is the mean,\n",
    "- $\\sigma$ is the standard deviation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0416787f",
   "metadata": {},
   "source": [
    "Example: Suppose a sensor output is a normally distributed with mean 50 and standard deviation 4. We compute the probability that the output is less than 58. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "ea59f656",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.float64(0.9772498680518208)"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mu = 50 \n",
    "sigma = 4\n",
    "proba = norm.cdf(58, loc=mu, scale=sigma)\n",
    "proba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "763cf868",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 32064 characters]",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(mu - 4*sigma, mu + 4*sigma, 400)\n",
    "pdf = norm.pdf(x, loc=mu, scale=sigma)\n",
    "\n",
    "plt.figure(figsize=(8,4))\n",
    "plt.plot(x, pdf)\n",
    "plt.axvline(58, linestyle='--')\n",
    "plt.xlabel(\"x\")\n",
    "plt.ylabel(\"Density\")\n",
    "plt.title(\"Normal Distribution\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "90c5658f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Simulated mean:  50.004935022325526\n",
      "Theoretical mean:  50\n",
      "Simulated std:  3.9780626491745017\n",
      "Theoretical std:  4\n"
     ]
    }
   ],
   "source": [
    "mu = 50\n",
    "sigma = 4 \n",
    "samples = 10_000\n",
    "\n",
    "normData = np.random.normal(loc=mu, scale=sigma, size=samples)\n",
    "print(\"Simulated mean: \", normData.mean())\n",
    "print(\"Theoretical mean: \", mu)\n",
    "print(\"Simulated std: \", normData.std(ddof=1))\n",
    "print(\"Theoretical std: \", sigma)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "0b94b1c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27456 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(normData, bins=50, density=True)\n",
    "plt.plot(x, pdf, 'or')\n",
    "plt.xlabel(\"Value\")\n",
    "plt.ylabel(\"Density\")\n",
    "plt.title(\"Normal: Simulation vs Theory\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "995adcee",
   "metadata": {},
   "source": [
    "# Central Limit Theorem\n",
    "The central limit theorem (CLT) states that the sampling distribution of the sample mean becomes approximately normal as the sample size increases."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "b22b9a32",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 11156 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "population = np.random.exponential(scale=2, size=100_000)\n",
    "plt.hist(population, bins=50, density=True)\n",
    "plt.xlabel(\"Value\")\n",
    "plt.ylabel(\"Density\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1d70f56",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "39dad6b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def SampleMeans(population, sampleSize, nRep=5_000):\n",
    "    means = []\n",
    "    for _ in range(nRep):\n",
    "        sample = np.random.choice(population, size=sampleSize, replace=True)\n",
    "        means.append(sample.mean())\n",
    "        pass\n",
    "    return np.array(means)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "2e324399",
   "metadata": {},
   "outputs": [],
   "source": [
    "mean5 = SampleMeans(population, 5)\n",
    "mean30 = SampleMeans(population, 30)\n",
    "mean100 = SampleMeans(population, 100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "e96babca",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 13456 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(mean5, bins=40, density=True, color=\"orange\",  alpha=0.3)\n",
    "plt.hist(mean30, bins=40, density=True, color=\"green\",  alpha=0.3)\n",
    "plt.hist(mean100, bins=40, density=True, color=\"blue\",  alpha=0.3)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "5a18e86e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Population mean:  1.9932073011758906\n",
      "Population var:  4.025192782387372\n",
      "Mean of 5 samples:  1.9998045611349438\n",
      "Var of 5 samples:  0.7837744844351563\n",
      "Mean of 30 samples:  1.992377755782367\n",
      "Var of 5 samples:  0.13206867208626297\n",
      "Mean of 100 samples:  1.994853961830046\n"
     ]
    }
   ],
   "source": [
    "# Numerical Check\n",
    "print(\"Population mean: \", population.mean())\n",
    "print(\"Population var: \", population.var())\n",
    "\n",
    "print(\"Mean of 5 samples: \", mean5.mean())\n",
    "print(\"Var of 5 samples: \", mean5.var(ddof=1))\n",
    "print(\"Mean of 30 samples: \", mean30.mean())\n",
    "print(\"Var of 5 samples: \", mean30.var(ddof=1))\n",
    "print(\"Mean of 100 samples: \", mean100.mean())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv (3.14.3)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
