{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "18990931",
   "metadata": {},
   "source": [
    "# DCT Laboratory — Volume II, Chapter 1\n",
    "## Introduction to Enterprise Optimization\n",
    "**Seed `26201`** · Companion to the chapter and AXIOM Module **AXIOM-01 (Vol. II)**\n",
    "\n",
    "Volume II's laboratory line opens where Volume I's closed: with choosing.\n",
    "Three instruments: a **closed-form allocation** (marginal values equalized at\n",
    "the optimum), **feasibility as conjunction** (a 36-point grid under three\n",
    "simultaneous constraints), and the proposition that **optimal decisions depend\n",
    "on objectives** — same feasible set, two different argmaxes.\n",
    "Mirrored in `DCT_V2_Ch01_Lab.xlsx`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e53a680",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:39:06.606815Z",
     "iopub.status.busy": "2026-07-13T23:39:06.606544Z",
     "iopub.status.idle": "2026-07-13T23:39:07.164715Z",
     "shell.execute_reply": "2026-07-13T23:39:07.163368Z"
    }
   },
   "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 = 26201\n",
    "# --- closed-form allocation: max 3*sqrt(x) + 4*sqrt(B-x), B=100 ---\n",
    "A1, A2, B = 3.0, 4.0, 100.0\n",
    "def f_alloc(x): return A1*np.sqrt(x) + A2*np.sqrt(B-x)\n",
    "X_STAR = B*A1**2/(A1**2+A2**2)          # 36\n",
    "# --- feasibility as conjunction: integer grid under three constraints ---\n",
    "def grid_points():\n",
    "    return [(x1,x2) for x1 in range(6) for x2 in range(6)]\n",
    "def feasible(p):\n",
    "    x1,x2 = p\n",
    "    return (x1+x2 <= 6) and (2*x1+x2 <= 8) and (x2 <= 4)\n",
    "# --- objectives choose optima ---\n",
    "def fA(p): return 3*p[0]+2*p[1]\n",
    "def fB(p): return 4*p[0]+p[1]\n",
    "\n",
    "def reference_values():\n",
    "    feas = [p for p in grid_points() if feasible(p)]\n",
    "    argA = max(feas, key=fA); argB = max(feas, key=fB)\n",
    "    mval = (A1/(2*np.sqrt(X_STAR)))/(A2/(2*np.sqrt(B-X_STAR)))\n",
    "    return {\n",
    "        \"x_star\": round(float(X_STAR),4),\n",
    "        \"f_star\": round(float(f_alloc(X_STAR)),4),\n",
    "        \"marginal_ratio\": round(float(mval),4),\n",
    "        \"n_grid\": len(grid_points()),\n",
    "        \"n_feasible\": len(feas),\n",
    "        \"fA_max\": fA(argA), \"fB_max\": fB(argB),\n",
    "        \"argA_x1\": argA[0], \"argA_x2\": argA[1],\n",
    "        \"argB_x1\": argB[0], \"argB_x2\": argB[1],\n",
    "    }\n",
    "if __name__ == \"__main__\":\n",
    "    [print(f\"{k:16s} {v}\") for k,v in reference_values().items()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2fcd97b2",
   "metadata": {},
   "source": [
    "## Panel 1 — The anatomy, in closed form\n",
    "Allocate a budget of 100 across two channels with square-root response:\n",
    "$f(x) = 3\\sqrt{x} + 4\\sqrt{100-x}$. The first-order condition equalizes\n",
    "marginal values, giving $x^* = 100 \\cdot 3^2/(3^2+4^2) = 36$ and $f^* = 50$ —\n",
    "every piece of the Anatomy of an Optimization Problem (Prop.) visible: decision,\n",
    "objective, constraint, optimum, and the optimality certificate (marginal ratio\n",
    "1.0000)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c058361a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:39:07.167061Z",
     "iopub.status.busy": "2026-07-13T23:39:07.166678Z",
     "iopub.status.idle": "2026-07-13T23:39:07.390624Z",
     "shell.execute_reply": "2026-07-13T23:39:07.389445Z"
    }
   },
   "outputs": [],
   "source": [
    "xs = np.linspace(0.5, 99.5, 300)\n",
    "fig, ax = plt.subplots(figsize=(8.0,4.2))\n",
    "ax.plot(xs, f_alloc(xs), c=\"#C8A24B\", lw=2.5)\n",
    "ax.scatter([X_STAR],[f_alloc(X_STAR)], c=\"#0B3D2E\", s=90, zorder=5, label=f\"x* = {X_STAR:.0f}, f* = {f_alloc(X_STAR):.0f}\")\n",
    "ax.set(xlabel=\"x (channel 1 budget)\", ylabel=\"f(x)\", title=\"3√x + 4√(100−x) — seed 26201\")\n",
    "ax.legend(frameon=False); ax.grid(alpha=.25); plt.tight_layout(); plt.show()\n",
    "m1 = A1/(2*np.sqrt(X_STAR)); m2 = A2/(2*np.sqrt(B-X_STAR))\n",
    "print(f\"marginal values at x*: {m1:.6f} vs {m2:.6f}   ratio {m1/m2:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b75a831",
   "metadata": {},
   "source": [
    "## Panel 2 — Feasibility is conjunction\n",
    "36 candidate decisions $(x_1, x_2) \\in \\{0..5\\}^2$; three constraints\n",
    "($x_1+x_2 \\le 6$, $2x_1+x_2 \\le 8$, $x_2 \\le 4$). Feasibility is Conjunction\n",
    "(Prop.): a point survives only if it satisfies ALL three — 19 of 36 do.\n",
    "The feasible region is the intersection, and the intersection is smaller than\n",
    "any of its parts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1cee6026",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:39:07.392936Z",
     "iopub.status.busy": "2026-07-13T23:39:07.392663Z",
     "iopub.status.idle": "2026-07-13T23:39:07.601205Z",
     "shell.execute_reply": "2026-07-13T23:39:07.599196Z"
    }
   },
   "outputs": [],
   "source": [
    "pts = grid_points(); feas = [p for p in pts if feasible(p)]\n",
    "fig, ax = plt.subplots(figsize=(6.2,5.0))\n",
    "inf = [p for p in pts if not feasible(p)]\n",
    "ax.scatter(*zip(*inf), c=\"#C9CCC9\", s=70, label=\"infeasible\")\n",
    "ax.scatter(*zip(*feas), c=\"#0B3D2E\", s=90, label=\"feasible (19)\")\n",
    "xs = np.linspace(-0.3,5.3,50)\n",
    "ax.plot(xs, 6-xs, c=\"#C8A24B\", lw=1.5); ax.plot(xs, 8-2*xs, c=\"#C8A24B\", lw=1.5); ax.axhline(4, c=\"#C8A24B\", lw=1.5)\n",
    "ax.set(xlim=(-0.4,5.4), ylim=(-0.4,5.6), xlabel=\"x1\", ylabel=\"x2\", title=\"Three constraints, one intersection\")\n",
    "ax.legend(frameon=False, fontsize=9); ax.grid(alpha=.2); plt.tight_layout(); plt.show()\n",
    "print(f\"grid {len(pts)}   feasible {len(feas)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3910a522",
   "metadata": {},
   "source": [
    "## Panel 3 — Optimal decisions depend on objectives\n",
    "Same 19 feasible points, two objectives. $f_A = 3x_1 + 2x_2$ crowns $(2,4)$ at\n",
    "14; $f_B = 4x_1 + x_2$ crowns $(4,0)$ at 16. Optimal Decisions Depend on\n",
    "Objectives (Prop.): the feasible region proposes, the objective disposes — and\n",
    "publishing the objective is what makes 'the optimal decision' a checkable claim\n",
    "(Volume I, Ch. 11's honesty campaign, arriving at decisions)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ba03161",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:39:07.603112Z",
     "iopub.status.busy": "2026-07-13T23:39:07.602896Z",
     "iopub.status.idle": "2026-07-13T23:39:07.609505Z",
     "shell.execute_reply": "2026-07-13T23:39:07.608604Z"
    }
   },
   "outputs": [],
   "source": [
    "feas = [p for p in grid_points() if feasible(p)]\n",
    "argA = max(feas, key=fA); argB = max(feas, key=fB)\n",
    "print(f\"objective A = 3x1+2x2 → argmax {argA}, value {fA(argA)}\")\n",
    "print(f\"objective B = 4x1+x2  → argmax {argB}, value {fB(argB)}\")\n",
    "print(\"distinct optima:\", argA != argB)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f24bda9",
   "metadata": {},
   "source": [
    "## Validation — agrees with `DCT_V2_Ch01_Lab.xlsx`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c79e7709",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T23:39:07.611486Z",
     "iopub.status.busy": "2026-07-13T23:39:07.611290Z",
     "iopub.status.idle": "2026-07-13T23:39:07.617980Z",
     "shell.execute_reply": "2026-07-13T23:39:07.616806Z"
    }
   },
   "outputs": [],
   "source": [
    "ref = reference_values()\n",
    "expected = {\"x_star\":36.0,\"f_star\":50.0,\"marginal_ratio\":1.0,\"n_grid\":36,\"n_feasible\":19,\n",
    " \"fA_max\":14,\"fB_max\":16,\"argA_x1\":2,\"argA_x2\":4,\"argB_x1\":4,\"argB_x2\":0}\n",
    "for k,v in expected.items():\n",
    "    assert abs(ref[k]-v)<5e-4, f\"MISMATCH {k}\"\n",
    "    print(f\"PASS  {k:16s} {ref[k]}\")\n",
    "print(\"\\nAll checkpoints agree — seed 26201. Volume II's line is open.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1106e89b",
   "metadata": {},
   "source": [
    "**Next**: Exercises 1.5–1.8 (Part C) reshape the constraints and re-count; AXIOM-01's anatomy bench labels every piece of the problem live. Solutions: IM Vol. II, Ch. 1."
   ]
  }
 ],
 "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
}
