{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e11460fe",
   "metadata": {},
   "source": [
    "# DCT Laboratory — Volume I, Chapter 15\n",
    "## Mathematical Formulation of Enterprise Optimization\n",
    "**Seed `26115`** · Companion to the chapter and AXIOM Module **AXIOM-15**\n",
    "\n",
    "**The GEOP, made small and solved exactly.** Allocate a budget of 6 across three\n",
    "capital investments to maximize output. The interior KKT point demands\n",
    "$I_F = -11.78$ — infeasible — so *feasibility precedes optimality* (Prop.) and\n",
    "the true optimum is a **corner** with the nonnegativity constraint active. Plus\n",
    "the Pareto scalarization sweep: the optimal decision is a property of the\n",
    "weights. Mirrored in `DCT_V1_Ch15_Lab.xlsx`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b55cec7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:17:26.509478Z",
     "iopub.status.busy": "2026-07-13T23:17:26.509237Z",
     "iopub.status.idle": "2026-07-13T23:17:26.978558Z",
     "shell.execute_reply": "2026-07-13T23:17:26.977405Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "plt.rcParams['figure.dpi']=110\n",
    "\n",
    "import numpy as np\n",
    "SEED = 26115\n",
    "K0    = np.array([40.0, 30.0, 20.0])       # F, H, T\n",
    "DELTA = np.array([0.02, 0.06, 0.10])\n",
    "ALPHA = np.array([0.30, 0.40, 0.30])\n",
    "A_TFP, BUDGET = 10.0, 6.0\n",
    "BASE = (1-DELTA)*K0                          # (39.2, 28.2, 18.0)\n",
    "\n",
    "def Y(I):\n",
    "    return float(A_TFP*np.prod((BASE + np.asarray(I))**ALPHA))\n",
    "\n",
    "def kkt_unconstrained():\n",
    "    \"\"\"Interior KKT: K'_i = alpha_i * (sum(BASE)+B); returns implied I.\"\"\"\n",
    "    S = BASE.sum() + BUDGET\n",
    "    return ALPHA*S - BASE\n",
    "\n",
    "def corner_optimum():\n",
    "    \"\"\"I_F = 0 binds; reallocate over (H, T) with renormalized shares.\"\"\"\n",
    "    S = BASE[1] + BASE[2] + BUDGET\n",
    "    w = ALPHA[1:]/ALPHA[1:].sum()\n",
    "    Kp = w*S\n",
    "    I = np.array([0.0, Kp[0]-BASE[1], Kp[1]-BASE[2]])\n",
    "    return I\n",
    "\n",
    "def pareto_sweep(ws=(0.0, 0.5, 1.0)):\n",
    "    \"\"\"Decision: I_H on a grid, I_T = B - I_H, I_F = 0.\n",
    "    f1 = Y (normalized by grid max), f2 = I_H/B (resilience buffer).\"\"\"\n",
    "    grid = np.arange(0, 6.5, 0.5)\n",
    "    ys = np.array([Y([0.0, ih, BUDGET-ih]) for ih in grid])\n",
    "    f1 = ys/ys.max(); f2 = grid/BUDGET\n",
    "    argmaxes = {}\n",
    "    for w in ws:\n",
    "        score = w*f1 + (1-w)*f2\n",
    "        argmaxes[w] = float(grid[int(np.argmax(score))])\n",
    "    return grid, ys, argmaxes\n",
    "\n",
    "def reference_values():\n",
    "    Iu = kkt_unconstrained()\n",
    "    Ic = corner_optimum()\n",
    "    Kp = BASE + Ic\n",
    "    marg = (ALPHA[1]/Kp[1])/(ALPHA[2]/Kp[2])\n",
    "    grid, ys, am = pareto_sweep()\n",
    "    return {\n",
    "        \"kkt_IF_unconstrained\": round(float(Iu[0]), 4),\n",
    "        \"IH_star\": round(float(Ic[1]), 4), \"IT_star\": round(float(Ic[2]), 4),\n",
    "        \"Y_star\": round(Y(Ic), 4),\n",
    "        \"Y_even_split\": round(Y([2.0, 2.0, 2.0]), 4),\n",
    "        \"marginal_ratio\": round(float(marg), 4),\n",
    "        \"argmax_IH_w1\": am[1.0], \"argmax_IH_w0\": am[0.0],\n",
    "        \"n_distinct_solutions\": len(set(am.values())),\n",
    "    }\n",
    "if __name__ == \"__main__\":\n",
    "    [print(f\"{k:22s} {v}\") for k,v in reference_values().items()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9ba0037",
   "metadata": {},
   "source": [
    "## Panel 1 — The KKT point that isn't feasible\n",
    "Interior first-order conditions give $K_i' = \\alpha_i \\cdot (\\text{total\n",
    "resources})$: elegant, closed-form — and demanding a **negative** financial\n",
    "investment of −11.78 (the optimizer wants to liquidate financial capital the\n",
    "constraint set won't release). The Feasible Enterprise Solution Theorem sends\n",
    "us to the boundary: with $I_F = 0$ active, the reduced problem over $(H, T)$ has\n",
    "its own interior optimum — and there, marginal products are exactly equal\n",
    "(ratio 1.0000): the Enterprise Optimality Conditions, verified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42068f64",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:17:26.980615Z",
     "iopub.status.busy": "2026-07-13T23:17:26.980281Z",
     "iopub.status.idle": "2026-07-13T23:17:26.988108Z",
     "shell.execute_reply": "2026-07-13T23:17:26.987053Z"
    }
   },
   "outputs": [],
   "source": [
    "Iu = kkt_unconstrained()\n",
    "print(\"unconstrained KKT investments:\", np.round(Iu,4), \"  ← I_F < 0: INFEASIBLE\")\n",
    "Ic = corner_optimum()\n",
    "print(\"corner optimum (I_F = 0 active):\", np.round(Ic,4))\n",
    "Kp = BASE + Ic\n",
    "print(f\"marginal products a_H/K_H' = {ALPHA[1]/Kp[1]:.6f}   a_T/K_T' = {ALPHA[2]/Kp[2]:.6f}   ratio = {(ALPHA[1]/Kp[1])/(ALPHA[2]/Kp[2]):.4f}\")\n",
    "print(f\"Y* = {Y(Ic):.4f}   vs even split (2,2,2): {Y([2,2,2]):.4f}   optimization premium: {Y(Ic)-Y([2,2,2]):.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49b46272",
   "metadata": {},
   "source": [
    "## Panel 2 — The objective landscape\n",
    "$Y$ along the active face ($I_F = 0$, $I_H + I_T = 6$): a smooth ridge with its\n",
    "peak at $I_H^* = 1.63$. The even split is close but not optimal — and the\n",
    "optimizer's 4-point premium is what Volume II will chase at enterprise scale,\n",
    "with dynamics and uncertainty attached."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2a0bea1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:17:26.990464Z",
     "iopub.status.busy": "2026-07-13T23:17:26.989737Z",
     "iopub.status.idle": "2026-07-13T23:17:27.213381Z",
     "shell.execute_reply": "2026-07-13T23:17:27.211984Z"
    }
   },
   "outputs": [],
   "source": [
    "grid = np.linspace(0, 6, 121)\n",
    "ys = [Y([0.0, ih, 6-ih]) for ih in grid]\n",
    "fig, ax = plt.subplots(figsize=(8.2,4.2))\n",
    "ax.plot(grid, ys, c=\"#C8A24B\", lw=2.5)\n",
    "Ic = corner_optimum()\n",
    "ax.scatter([Ic[1]],[Y(Ic)], c=\"#0B3D2E\", s=90, zorder=5, label=f\"optimum I_H* = {Ic[1]:.4f}\")\n",
    "ax.scatter([2],[Y([0,2,4])], c=\"#8A8F8B\", s=60, zorder=5)\n",
    "ax.set(xlabel=\"I_H  (I_T = 6 − I_H, I_F = 0)\", ylabel=\"output Y\",\n",
    "       title=\"The GEOP's active face — seed 26115\")\n",
    "ax.legend(frameon=False); ax.grid(alpha=.25); plt.tight_layout(); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23fab2bf",
   "metadata": {},
   "source": [
    "## Panel 3 — Multi-objective: the weights choose the point\n",
    "Two objectives: output $f_1 = Y$ (normalized) and resilience buffer $f_2 =\n",
    "I_H/6$. Scalarize with weight $w$ on output and sweep: at $w = 1$ the optimizer\n",
    "picks $I_H = 1.5$ (the grid's output peak); at $w = 0$ it picks 6.0 (all\n",
    "buffer). Two distinct solutions across the sweep — the Pareto Frontier Theorem\n",
    "in one table, and Chapter 11's aggregation lesson landing on decisions rather\n",
    "than rankings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b3044a6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:17:27.215311Z",
     "iopub.status.busy": "2026-07-13T23:17:27.215073Z",
     "iopub.status.idle": "2026-07-13T23:17:27.222741Z",
     "shell.execute_reply": "2026-07-13T23:17:27.221425Z"
    }
   },
   "outputs": [],
   "source": [
    "grid, ys, am = pareto_sweep()\n",
    "f1 = ys/ys.max(); f2 = grid/6\n",
    "print(f\"{'I_H':>5s} {'Y':>10s} {'f1':>7s} {'f2':>6s}\")\n",
    "for ih, y, a, b in zip(grid, ys, f1, f2):\n",
    "    print(f\"{ih:5.1f} {y:10.4f} {a:7.4f} {b:6.3f}\")\n",
    "print(\"\\nargmax by weight on output:\", {w: v for w,v in am.items()})\n",
    "print(\"distinct optimal decisions:\", len(set(am.values())))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "535e7469",
   "metadata": {},
   "source": [
    "## Validation — agrees with `DCT_V1_Ch15_Lab.xlsx`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b56cabc3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:17:27.225055Z",
     "iopub.status.busy": "2026-07-13T23:17:27.224328Z",
     "iopub.status.idle": "2026-07-13T23:17:27.231010Z",
     "shell.execute_reply": "2026-07-13T23:17:27.230069Z"
    }
   },
   "outputs": [],
   "source": [
    "ref = reference_values()\n",
    "expected = {\"kkt_IF_unconstrained\":-11.78,\"IH_star\":1.6286,\"IT_star\":4.3714,\n",
    " \"Y_star\":296.9935,\"Y_even_split\":292.9415,\"marginal_ratio\":1.0,\n",
    " \"argmax_IH_w1\":1.5,\"argmax_IH_w0\":6.0,\"n_distinct_solutions\":2}\n",
    "for k,v in expected.items():\n",
    "    assert abs(ref[k]-v)<5e-4, f\"MISMATCH {k}\"\n",
    "    print(f\"PASS  {k:22s} {ref[k]}\")\n",
    "print(\"\\nAll checkpoints agree — seed 26115.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e04c0d0",
   "metadata": {},
   "source": [
    "**Next**: Exercises 15.9–15.12 (Part C) move the budget and watch the active set change; AXIOM-15's GEOP console is the volume's capstone instrument. Solutions: IM Ch. 15."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 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.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
