{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8ff484e0",
   "metadata": {},
   "source": [
    "# Clase 1 — Modelado de Cadenas de Markov en Tiempo Continuo (CTMC)\n",
    "## Caso: subsistema reparable de una planta embotelladora\n",
    "\n",
    "**Contexto (basado en un paper real).** Gayathri (2025), *\"A Continuous-Time Markov Chain Approach for Availability Analysis of a Repairable Engineering System\"* (IJFMR), modela una planta embotelladora de 8 subsistemas como una CTMC de 32 estados, y usa las ecuaciones diferenciales de Kolmogorov para calcular la disponibilidad del sistema en el tiempo.\n",
    "\n",
    "En esta clase modelamos, con el mismo enfoque, **uno solo de esos subsistemas** — la Unidad de Lavado (B) — que según el paper \"consiste en dos unidades, una operando y otra en espera fría (standby); la unidad de respaldo opera en un estado de capacidad reducida; la falla completa ocurre cuando ambas unidades fallan\". En la Clase 2 retomaremos este mismo sistema para resolverlo con las ecuaciones de Kolmogorov de forma explícita.\n",
    "\n",
    "Curso: Modelado de Sistemas bajo Incertidumbre · Universidad de los Andes · 2026-20\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ef551ca",
   "metadata": {},
   "source": [
    "## Descripción del problema\n",
    "\n",
    "La unidad de lavado de la planta tiene una máquina principal y una máquina de respaldo (en frío). Mientras la principal funciona, la de respaldo está apagada. Si la principal falla, la de respaldo entra a operar de inmediato (en capacidad reducida) mientras se repara la principal. Si la de respaldo también falla antes de que la principal quede reparada, el subsistema queda completamente fuera de servicio.\n",
    "\n",
    "Una unidad reparada queda \"como nueva\" (supuesto del paper).\n",
    "\n",
    "**Variable de estado.** $X(t)$: ...\n",
    "\n",
    "**Espacio de estados.** ... \n",
    "- Estado ...\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "019caaf4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# importar librerías\n",
    "import numpy as np\n",
    "from jmarkov.ctmc import ctmc\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7a991e4",
   "metadata": {},
   "source": [
    "## Parámetros del problema\n",
    "\n",
    "- $\\lambda_1=0.02$ fallas/día: tasa de falla de la unidad principal (vida media de 50 días).\n",
    "- $\\lambda_2=0.05$ fallas/día: tasa de falla de la unidad de respaldo mientras opera (vida media de 20 días, más exigida).\n",
    "- $\\mu_1=1$ reparaciones/día: tasa de reparación de la unidad principal (tiempo medio de reparación: 1 día).\n",
    "- $\\mu_2=0.5$ reparaciones/día: tasa de reparación cuando ambas unidades fallaron (tiempo medio: 2 días, reparación más compleja)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b92bc36",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 1: define lda1, lda2, mu1, mu2 con los valores dados arriba\n",
    "lda1 = None\n",
    "lda2 = None\n",
    "mu1 = None\n",
    "mu2 = None\n",
    "print(f'lda1={lda1}, lda2={lda2}, mu1={mu1}, mu2={mu2}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2134dcb",
   "metadata": {},
   "source": [
    "## Diagrama de transiciones\n",
    "\n",
    "```\n",
    "   ...\n",
    "```\n",
    "\n",
    "## Matriz generadora\n",
    "\n",
    "$$Q=\\begin{pmatrix} \\end{pmatrix}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "212722a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 2: construye la matriz generadora Q (nxn) \n",
    "Q = np.array([\n",
    "    # fila 0 \n",
    "    # fila 1 \n",
    "    # fila 2 \n",
    "])\n",
    "\n",
    "mc = ctmc(Q)\n",
    "print(f'Q=\\n{mc.generator}')\n",
    "\n",
    "# --- prueba rápida (no la modifiques) ---\n",
    "assert np.allclose(Q.sum(axis=1), 0), 'cada fila de Q debe sumar 0'\n",
    "print('OK: Q es una matriz generadora válida (filas suman 0).')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "744bf507",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 3: construye el vector de condiciones iniciales alpha\n",
    "# el subsistema arranca en el estado ... \n",
    "alpha = np.array([])\n",
    "print(f'alpha={alpha}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9ce693d",
   "metadata": {},
   "source": [
    "## Evaluar la distribución transitoria\n",
    "\n",
    "Calcula $\\pi(t)=[\\pi_0(t),\\pi_1(t),\\pi_2(t)]$ para $t\\in\\{0.5,\\,1,\\,5,\\,10,\\,50\\}$ días usando `mc.transient_probabilities(t, alpha)`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41551f73",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 4: evalúa pi(t) para cada uno de los tiempos dados, usando un ciclo for\n",
    "tiempos = [0.5, 1, 5, 10, 50]\n",
    "for t in tiempos:\n",
    "    pi_t = None  # usa mc.transient_probabilities(t, alpha)\n",
    "    print(f'pi({t})={pi_t}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eecccff6",
   "metadata": {},
   "source": [
    "## Disponibilidad del subsistema\n",
    "\n",
    "El subsistema sigue disponible (aunque sea en capacidad reducida) mientras no esté en el estado 2. La disponibilidad en el instante $t$ es:\n",
    "\n",
    "$$Av(t)=P(X(t)\\neq 2)= ... $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f54efb0a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 5: calcula Av(t) =  para cada uno de los mismos tiempos\n",
    "for t in tiempos:\n",
    "    pi_t = mc.transient_probabilities(t, alpha)\n",
    "    Av_t = None\n",
    "    print(f'Av({t}) = {Av_t:.5f}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d66636d",
   "metadata": {},
   "source": [
    "## Evaluar la distribución estacionaria\n",
    "\n",
    "Calcula $\\pi=\\lim_{t\\to\\infty}\\pi(t)$ con `mc.steady_state()`, y la disponibilidad estacionaria $Av=.. + .. + $."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6ee768a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO 6: calcula la distribución estacionaria y la disponibilidad estacionaria\n",
    "ss = None  # usa mc.steady_state()\n",
    "print(f'pi={ss}')\n",
    "\n",
    "Av = None\n",
    "print(f'Disponibilidad estacionaria Av = {Av:.5f}')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "582bb14c",
   "metadata": {},
   "source": [
    "## Conclusión\n",
    "\n",
    "_¿Qué tan rápido converge la disponibilidad del subsistema a su valor estacionario? ¿Qué estado domina la distribución de probabilidad en el largo plazo, y por qué tiene sentido dado los valores de $\\lambda$ y $\\mu$?_"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "research (3.12.9)",
   "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": 5
}
