{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "34caedb6",
   "metadata": {},
   "source": [
    "# Producción de carros — control de tolerancias en el ensamble de una puerta\n",
    "\n",
    "**Objetivo.** Estimar por simulación de Monte Carlo la probabilidad de que una puerta requiera reproceso por quedar fuera de tolerancia, generando los números pseudoaleatorios con un generador congruencial lineal (LCG) propio, y comparar contra la solución analítica.\n",
    "\n",
    "Curso: Modelado de Sistemas bajo Incertidumbre · Universidad de los Andes · 2026-20\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c53ead9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from scipy.special import ndtri\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "N = 50_000\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6c8eb25",
   "metadata": {},
   "source": [
    "## Datos del problema\n",
    "\n",
    "Una puerta se ensambla a partir de 4 piezas cuya dimensión crítica (mm) es normal e independiente:\n",
    "\n",
    "| Pieza | Media (mm) | Desv. estándar (mm) |\n",
    "|---|---:|---:|\n",
    "| Marco estructural ($X_1$) | 452.0 | 0.35 |\n",
    "| Soporte de bisagra ($X_2$) | 18.0 | 0.10 |\n",
    "| Canal de ventana ($X_3$) | 25.5 | 0.15 |\n",
    "| Empaque de sellado ($X_4$) | 4.2 | 0.05 |\n",
    "\n",
    "Holgura de ensamblaje: $G = X_1 - X_2 - X_3 - X_4$. La puerta necesita reproceso si $G \\notin [403.5,\\ 404.5]$ mm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b07cfec7",
   "metadata": {},
   "source": [
    "## Generador de números pseudoaleatorios (LCG)\n",
    "\n",
    "\n",
    "Parámetros $a=1664525$, $c=1013904223$, $m=2^{32}$, semilla $X_0=2026$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "024c294e",
   "metadata": {},
   "outputs": [],
   "source": [
    "A_LCG, C_LCG, M_LCG = 1664525, 1013904223, 2**32\n",
    "SEMILLA_LCG = 2026\n",
    "\n",
    "def siguiente_uniforme(estado):\n",
    "    \"\"\"\n",
    "    Un paso del LCG: estado_nuevo = (A_LCG*estado + C_LCG) mod M_LCG ; u = estado_nuevo / M_LCG\n",
    "    Retorna (u, estado_nuevo).\n",
    "    \"\"\"\n",
    "    # TODO 1: nuevo_estado = (A_LCG * estado + C_LCG) % M_LCG\n",
    "    # TODO 2: u = nuevo_estado / M_LCG\n",
    "    # TODO 3: retorna (u, nuevo_estado)\n",
    "    raise NotImplementedError(\"Implementa siguiente_uniforme\")\n",
    "\n",
    "# --- prueba rápida (no la modifiques) ---\n",
    "u1, e1 = siguiente_uniforme(SEMILLA_LCG)\n",
    "u2, e2 = siguiente_uniforme(e1)\n",
    "assert 0 <= u1 < 1 and 0 <= u2 < 1\n",
    "assert e1 != SEMILLA_LCG and e2 != e1\n",
    "print(\"OK: siguiente_uniforme pasa la prueba básica. u1 =\", round(u1, 4), \" u2 =\", round(u2, 4))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57f636b7",
   "metadata": {},
   "source": [
    "## Simulación\n",
    "\n",
    "Sigue el pseudocódigo exactamente: dentro del ciclo, para cada una de las 4 piezas, obtén un nuevo `u` con `siguiente_uniforme` y transforma con `ndtri` a la pieza `X_i` correspondiente. Con las 4 piezas, calcula `G` y el indicador `I` de reproceso."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4242e92a",
   "metadata": {},
   "outputs": [],
   "source": [
    "medias = np.array([452.0, 18.0, 25.5, 4.2])\n",
    "sds = np.array([0.35, 0.10, 0.15, 0.05])\n",
    "L, U = 403.5, 404.5\n",
    "\n",
    "G = np.empty(N)\n",
    "I = np.empty(N)\n",
    "estado = SEMILLA_LCG\n",
    "# TODO:\n",
    "#  \n",
    "#   \n",
    "#\n",
    "\n",
    "\n",
    "\n",
    "assert G.shape == (N,) and I.shape == (N,)\n",
    "print(\"OK: G e I fueron calculados para las\", N, \"réplicas, usando el LCG.\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6164234c",
   "metadata": {},
   "source": [
    "## Métricas\n",
    "\n",
    "Calcula, a partir de `G` e `I`: la media y desviación estándar de `G`, el error estándar de esa media y su intervalo de confianza al 95%, la proporción estimada de reproceso $\\hat p$ con su error estándar e intervalo de confianza, y el error relativo de $\\hat p$ frente al valor analítico (0.3291)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f79fd10",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: Gbar = \n",
    "# TODO: s_G =\n",
    "# TODO: SE_G = \n",
    "# TODO: IC_G = \n",
    "\n",
    "# TODO: p_hat = \n",
    "# TODO: s_p = \n",
    "# TODO: SE_p = \n",
    "# TODO: IC_p = \n",
    "\n",
    "p_analitico = 0.3291\n",
    "# TODO: error_rel\n",
    "\n",
    "# TODO: imprime Gbar, s_G, IC_G, p_hat, SE_p, IC_p y error_rel con una etiqueta clara para cada uno\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8e7e3af",
   "metadata": {},
   "source": [
    "## Histograma de G"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c97d4e60",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: arma un histograma de G (bins=60, density=True)\n",
    "# TODO: agrega líneas verticales en L, en U y en Gbar\n",
    "# TODO: etiqueta los ejes, pon título y leyenda\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fce63ff",
   "metadata": {},
   "source": [
    "## Conclusión\n",
    "\n",
    "_Compara tu p_hat simulado (con el LCG) contra el valor analítico (0.3291) y escribe 1-2 conclusiones._"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
