{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import stan\n",
    "import arviz as az\n",
    "\n",
    "# stan problems\n",
    "import nest_asyncio\n",
    "nest_asyncio.apply()\n",
    "\n",
    "np.random.seed(42)\n",
    "N = 100\n",
    "alpha = 2.3\n",
    "beta = 4.0\n",
    "sigma = 2.0\n",
    "x = np.random.normal(size=N)\n",
    "y = alpha + beta * x + sigma * np.random.normal(size=N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mu_0 = 3\n",
    "sigma_0 = 3\n",
    "sample_mean = np.mean(y)\n",
    "n = N\n",
    "\n",
    "# posterior\n",
    "sigma_sq = sigma ** 2\n",
    "sigma_0_sq = sigma_0 ** 2\n",
    "\n",
    "mu_post = ((n / sigma_sq) * sample_mean + (1 / sigma_0_sq) * mu_0) / (n / sigma_sq + 1 / sigma_0_sq)\n",
    "sigma_post_sq = 1 / (n / sigma_sq + 1 / sigma_0_sq)\n",
    "sigma_post = np.sqrt(sigma_post_sq)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26300 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "prior_samples = np.random.normal(mu_0, sigma_0, 10000)\n",
    "posterior_samples = np.random.normal(mu_post, sigma_post, 10000)\n",
    "\n",
    "plt.hist(prior_samples, bins=50, density=True, alpha=0.5, label='Prior')\n",
    "plt.hist(posterior_samples, bins=50, density=True, alpha=0.5, label='Posterior')\n",
    "\n",
    "plt.legend()\n",
    "plt.xlabel('Average Height (meters)')\n",
    "plt.ylabel('Density')\n",
    "plt.title('Prior vs Posterior')\n",
    "plt.savefig('Q5.png')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "stanCode = \"\"\"\n",
    "data {\n",
    "  int<lower=0> N;  // observations\n",
    "  vector[N] x;     // predictor\n",
    "  vector[N] y;     // response\n",
    "}\n",
    "parameters {\n",
    "  real alpha;      // intercept\n",
    "  real beta;       // slope\n",
    "  real<lower=0> sigma;  // noise standard deviation\n",
    "}\n",
    "model {\n",
    "  sigma ~ inv_gamma(1, 1);   // noise\n",
    "  alpha ~ normal(0, 10);     // intercept\n",
    "  beta ~ normal(0, 10);      // slope\n",
    "  y ~ normal(alpha + beta * x, sigma);\n",
    "}\n",
    "\"\"\"\n",
    "\n",
    "data = {\n",
    "    'N': N,\n",
    "    'x': x,\n",
    "    'y': y\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Building...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "Building: found in cache, done.Sampling:   0%\n",
      "Sampling:  25% (3000/12000)\n",
      "Sampling:  50% (6000/12000)\n",
      "Sampling:  75% (9000/12000)\n",
      "Sampling: 100% (12000/12000)\n",
      "Sampling: 100% (12000/12000), done.\n",
      "Messages received during sampling:\n",
      "  Gradient evaluation took 4.2e-05 seconds\n",
      "  1000 transitions using 10 leapfrog steps per transition would take 0.42 seconds.\n",
      "  Adjust your expectations accordingly!\n",
      "  Informational Message: The current Metropolis proposal is about to be rejected because of the following issue:\n",
      "  Exception: normal_lpdf: Scale parameter is 0, but must be positive! (in '/tmp/httpstan_lipc1ba5/model_oj7ef663.stan', line 16, column 2 to column 38)\n",
      "  If this warning occurs sporadically, such as for highly constrained variable types like covariance matrices, then the sampler is fine,\n",
      "  but if this warning occurs often then your model may be either severely ill-conditioned or misspecified.\n",
      "  Gradient evaluation took 2.8e-05 seconds\n",
      "  1000 transitions using 10 leapfrog steps per transition would take 0.28 seconds.\n",
      "  Adjust your expectations accordingly!\n",
      "  Gradient evaluation took 2.2e-05 seconds\n",
      "  1000 transitions using 10 leapfrog steps per transition would take 0.22 seconds.\n",
      "  Adjust your expectations accordingly!\n",
      "  Informational Message: The current Metropolis proposal is about to be rejected because of the following issue:\n",
      "  Exception: normal_lpdf: Scale parameter is 0, but must be positive! (in '/tmp/httpstan_lipc1ba5/model_oj7ef663.stan', line 16, column 2 to column 38)\n",
      "  If this warning occurs sporadically, such as for highly constrained variable types like covariance matrices, then the sampler is fine,\n",
      "  but if this warning occurs often then your model may be either severely ill-conditioned or misspecified.\n",
      "  Gradient evaluation took 3.8e-05 seconds\n",
      "  1000 transitions using 10 leapfrog steps per transition would take 0.38 seconds.\n",
      "  Adjust your expectations accordingly!\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>mean</th>\n",
       "      <th>sd</th>\n",
       "      <th>hdi_3%</th>\n",
       "      <th>hdi_97%</th>\n",
       "      <th>mcse_mean</th>\n",
       "      <th>mcse_sd</th>\n",
       "      <th>ess_bulk</th>\n",
       "      <th>ess_tail</th>\n",
       "      <th>r_hat</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>alpha</th>\n",
       "      <td>2.315</td>\n",
       "      <td>0.193</td>\n",
       "      <td>1.946</td>\n",
       "      <td>2.672</td>\n",
       "      <td>0.002</td>\n",
       "      <td>0.002</td>\n",
       "      <td>7672.0</td>\n",
       "      <td>5912.0</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>beta</th>\n",
       "      <td>3.716</td>\n",
       "      <td>0.214</td>\n",
       "      <td>3.305</td>\n",
       "      <td>4.108</td>\n",
       "      <td>0.003</td>\n",
       "      <td>0.002</td>\n",
       "      <td>6876.0</td>\n",
       "      <td>5564.0</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>sigma</th>\n",
       "      <td>1.910</td>\n",
       "      <td>0.140</td>\n",
       "      <td>1.662</td>\n",
       "      <td>2.175</td>\n",
       "      <td>0.002</td>\n",
       "      <td>0.002</td>\n",
       "      <td>7423.0</td>\n",
       "      <td>5615.0</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        mean     sd  hdi_3%  hdi_97%  mcse_mean  mcse_sd  ess_bulk  ess_tail  \\\n",
       "alpha  2.315  0.193   1.946    2.672      0.002    0.002    7672.0    5912.0   \n",
       "beta   3.716  0.214   3.305    4.108      0.003    0.002    6876.0    5564.0   \n",
       "sigma  1.910  0.140   1.662    2.175      0.002    0.002    7423.0    5615.0   \n",
       "\n",
       "       r_hat  \n",
       "alpha    1.0  \n",
       "beta     1.0  \n",
       "sigma    1.0  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = stan.build(stanCode, data=data)\n",
    "fit = model.sample(num_samples=2000, num_chains=4)\n",
    "\n",
    "az.summary(az.from_pystan(fit))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "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.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
