{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "dd0017f2",
   "metadata": {},
   "source": [
    "# DCT Laboratory — Volume II, Chapter 12\n",
    "## Multi-Objective Enterprise Optimization\n",
    "**Seed `26212`** · Companion to the chapter and AXIOM Module **AXIOM-12 (Vol. II)**\n",
    "\n",
    "When the enterprise wants several things at once. Three acts: **Pareto\n",
    "dominance sorted by hand** over eight candidate policies (five efficient,\n",
    "three dominated), the **scalarization gap exhibited** — policy D sits in a\n",
    "non-convex dent of the frontier that *no weighted sum can select*, but a\n",
    "weighted-Chebyshev compromise finds it — and a **continuous frontier** where\n",
    "the Trade-Off Theorem's slope identity is verified point by point.\n",
    "Mirrored in `DCT_V2_Ch12_Lab.xlsx`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e11f629f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-14T00:40:32.580248Z",
     "iopub.status.busy": "2026-07-14T00:40:32.579937Z",
     "iopub.status.idle": "2026-07-14T00:40:33.038159Z",
     "shell.execute_reply": "2026-07-14T00:40:33.037004Z"
    }
   },
   "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 = 26212\n",
    "NAMES = list(\"ABCDEFGH\")\n",
    "PTS = {\"A\":(2,9.0),\"B\":(4,8.0),\"C\":(5,5.0),\"D\":(6,6.5),\"E\":(7,4.0),\"F\":(8,6.0),\"G\":(9,2.0),\"H\":(3,6.0)}\n",
    "def dominated(name):\n",
    "    g,r = PTS[name]\n",
    "    return any((g2 >= g and r2 >= r and (g2 > g or r2 > r)) for n2,(g2,r2) in PTS.items() if n2 != name)\n",
    "def pareto_set(): return [n for n in NAMES if not dominated(n)]\n",
    "def ws_winner(w):\n",
    "    vals = {n: w*g + (1-w)*r for n,(g,r) in PTS.items()}\n",
    "    return max(vals, key=vals.get)\n",
    "def ws_selects_D():\n",
    "    return int(any(ws_winner(round(0.05*i,2)) == \"D\" for i in range(21)))\n",
    "# weighted Chebyshev compromise to the ideal point (9, 9), weights (1, 1.5)\n",
    "IDEAL = (9.0, 9.0); WCH = (1.0, 1.5)\n",
    "def cheb(name):\n",
    "    g,r = PTS[name]\n",
    "    return max(WCH[0]*abs(IDEAL[0]-g), WCH[1]*abs(IDEAL[1]-r))\n",
    "def cheb_winner():\n",
    "    return min(pareto_set(), key=cheb)\n",
    "# continuous frontier: f1 = x, f2 = 1 - x^2 on [0,1]; weighted sum w*f1+(1-w)*f2\n",
    "def x_star(w): return min(1.0, w/(2*(1-w))) if w < 1 else 1.0\n",
    "def w_corner(step=0.1):\n",
    "    for i in range(1,10):\n",
    "        w = round(step*i,2)\n",
    "        if w/(2*(1-w)) >= 1.0: return w\n",
    "    return None\n",
    "\n",
    "def reference_values():\n",
    "    return {\n",
    "        \"n_candidates\": len(NAMES),\n",
    "        \"n_pareto\": len(pareto_set()),\n",
    "        \"n_dominated\": len(NAMES)-len(pareto_set()),\n",
    "        \"D_is_pareto\": int(\"D\" in pareto_set()),\n",
    "        \"ws_selects_D\": ws_selects_D(),\n",
    "        \"cheb_D\": round(cheb(\"D\"),4), \"cheb_F\": round(cheb(\"F\"),4),\n",
    "        \"cheb_winner_is_D\": int(cheb_winner() == \"D\"),\n",
    "        \"x_star_w05\": round(x_star(0.5),4),\n",
    "        \"f1_w05\": round(x_star(0.5),4),\n",
    "        \"f2_w05\": round(1-x_star(0.5)**2,4),\n",
    "        \"tradeoff_w05\": round(-2*x_star(0.5),4),\n",
    "        \"w_corner\": w_corner(),\n",
    "    }\n",
    "if __name__ == \"__main__\":\n",
    "    print(\"pareto set:\", pareto_set(), \"  chebyshev winner:\", cheb_winner())\n",
    "    [print(f\"{k:18s} {v}\") for k,v in reference_values().items()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcef64a9",
   "metadata": {},
   "source": [
    "## Panel 1 — Dominance does the first cut\n",
    "Eight candidate policies scored on growth and resilience. Pareto Dominance\n",
    "(Def.): a policy is dominated if another is at least as good in both\n",
    "objectives and strictly better in one. Three fall — C to D, E to F, H to B —\n",
    "and **five survive**: the Pareto set $\\{A, B, D, F, G\\}$ (Pareto Optimal\n",
    "Enterprise Policy, Def.). No Single Efficient Solution Optimizes All\n",
    "Objectives (Prop.): among survivors, every move that gains growth costs\n",
    "resilience — the disagreement that remains after logic has done all it can."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b821433",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-14T00:40:33.040716Z",
     "iopub.status.busy": "2026-07-14T00:40:33.039880Z",
     "iopub.status.idle": "2026-07-14T00:40:33.319514Z",
     "shell.execute_reply": "2026-07-14T00:40:33.318490Z"
    }
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(figsize=(7.6,4.6))\n",
    "for n,(g,r) in PTS.items():\n",
    "    on = n in pareto_set()\n",
    "    ax.scatter([g],[r], s=110, c=\"#C8A24B\" if on else \"#8A8F8B\", zorder=5,\n",
    "               edgecolors=\"#0B3D2E\", linewidths=1.2 if on else 0.5)\n",
    "    ax.annotate(n, (g,r), textcoords=\"offset points\", xytext=(7,5), fontsize=11,\n",
    "                color=\"#0B3D2E\" if on else \"#8A8F8B\", fontweight=\"bold\" if on else \"normal\")\n",
    "ps = sorted([PTS[n] for n in pareto_set()])\n",
    "ax.plot([p[0] for p in ps],[p[1] for p in ps], \"--\", c=\"#C8A24B\", lw=1.6, alpha=.7)\n",
    "ax.set(xlabel=\"growth\", ylabel=\"resilience\", title=\"Five efficient, three dominated — seed 26212\")\n",
    "ax.grid(alpha=.25); plt.tight_layout(); plt.show()\n",
    "print(f\"Pareto set: {pareto_set()}   dominated: {[n for n in NAMES if dominated(n)]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a96c9f58",
   "metadata": {},
   "source": [
    "## Panel 2 — The scalarization gap, and the compromise that closes it\n",
    "The Weighted-Sum Representation Theorem selects only points on the frontier's\n",
    "*convex* upper boundary. Policy D $(6, 6.5)$ is Pareto-optimal but sits in a\n",
    "**dent** — sweeping the weight $w$ across all 21 grid values, D wins\n",
    "**zero** times: some efficient policies are invisible to every weighted sum.\n",
    "The Enterprise Compromise Solution (Def.): minimize the weighted Chebyshev\n",
    "distance to the ideal point $(9, 9)$ with stakeholder weights $(1, 1.5)$ —\n",
    "and **D wins** (3.75 against F's 4.5). Stakeholder Preferences Select Among\n",
    "Pareto-Optimal Solutions (Prop.), with a method whose reach covers the whole\n",
    "frontier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5fdf0920",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-14T00:40:33.322135Z",
     "iopub.status.busy": "2026-07-14T00:40:33.321298Z",
     "iopub.status.idle": "2026-07-14T00:40:33.327718Z",
     "shell.execute_reply": "2026-07-14T00:40:33.326794Z"
    }
   },
   "outputs": [],
   "source": [
    "winners = [ws_winner(round(0.05*i,2)) for i in range(21)]\n",
    "print(\"weighted-sum winners across w = 0.00 .. 1.00:\", \"\".join(winners))\n",
    "print(f\"D selected by any weighted sum: {bool(ws_selects_D())}\")\n",
    "print(f\"\\nweighted Chebyshev to ideal (9,9), weights (1, 1.5):\")\n",
    "for n in pareto_set(): print(f\"  {n}: {cheb(n):.4f}\")\n",
    "print(f\"compromise winner: {cheb_winner()} — the dent, reached\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94a55ecd",
   "metadata": {},
   "source": [
    "## Panel 3 — The continuous frontier and the trade-off identity\n",
    "Objectives $f_1 = x$, $f_2 = 1 - x^2$ on $[0, 1]$: every $x$ is efficient\n",
    "(Pareto Frontier Existence Theorem). The weighted sum $wf_1 + (1-w)f_2$ has\n",
    "interior optimum $x^*(w) = w/2(1-w)$ — at $w = 0.5$: $x^* = 0.5$,\n",
    "$(f_1, f_2) = (0.5, 0.75)$, and the frontier's slope there is\n",
    "$df_2/df_1 = -2x = -1$: exactly $-w/(1-w)$ — the **Enterprise Trade-Off\n",
    "Theorem**: the chosen point is where the frontier's exchange rate equals the\n",
    "decision-maker's. Past $w = 2/3$ the optimum hits the corner $x = 1$: strong\n",
    "enough growth preference exhausts the frontier (first grid $w$: 0.7)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9ada421f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-14T00:40:33.330179Z",
     "iopub.status.busy": "2026-07-14T00:40:33.329476Z",
     "iopub.status.idle": "2026-07-14T00:40:33.528759Z",
     "shell.execute_reply": "2026-07-14T00:40:33.527412Z"
    }
   },
   "outputs": [],
   "source": [
    "xs = np.linspace(0, 1, 200)\n",
    "fig, ax = plt.subplots(figsize=(7.6,4.4))\n",
    "ax.plot(xs, 1-xs**2, c=\"#0B3D2E\", lw=2.4, label=\"frontier f2 = 1 − f1²\")\n",
    "for w in (0.3, 0.5, 0.7):\n",
    "    x = x_star(w)\n",
    "    ax.scatter([x],[1-x*x], s=80, c=\"#C8A24B\", zorder=5)\n",
    "    ax.annotate(f\"w={w}\", (x,1-x*x), textcoords=\"offset points\", xytext=(6,6), fontsize=10, color=\"#0B3D2E\")\n",
    "ax.set(xlabel=\"f1 (growth)\", ylabel=\"f2 (resilience)\", title=\"The weight ratio picks the tangency — seed 26212\")\n",
    "ax.legend(frameon=False); ax.grid(alpha=.25); plt.tight_layout(); plt.show()\n",
    "print(f\"w=0.5: x* = {x_star(0.5):.4f}, f = ({x_star(0.5):.4f}, {1-x_star(0.5)**2:.4f}), slope = {-2*x_star(0.5):.4f}\")\n",
    "print(f\"corner reached at grid w = {w_corner()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d037e97e",
   "metadata": {},
   "source": [
    "## Validation — agrees with `DCT_V2_Ch12_Lab.xlsx`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c7f1a01",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-14T00:40:33.530763Z",
     "iopub.status.busy": "2026-07-14T00:40:33.530558Z",
     "iopub.status.idle": "2026-07-14T00:40:33.536977Z",
     "shell.execute_reply": "2026-07-14T00:40:33.535971Z"
    }
   },
   "outputs": [],
   "source": [
    "ref = reference_values()\n",
    "expected = {\"n_candidates\":8,\"n_pareto\":5,\"n_dominated\":3,\"D_is_pareto\":1,\"ws_selects_D\":0,\n",
    " \"cheb_D\":3.75,\"cheb_F\":4.5,\"cheb_winner_is_D\":1,\"x_star_w05\":0.5,\"f1_w05\":0.5,\n",
    " \"f2_w05\":0.75,\"tradeoff_w05\":-1.0,\"w_corner\":0.7}\n",
    "for k,v in expected.items():\n",
    "    assert abs(ref[k]-v)<5e-4, f\"MISMATCH {k}\"\n",
    "    print(f\"PASS  {k:18s} {ref[k]}\")\n",
    "print(\"\\nAll checkpoints agree — seed 26212.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2833ce2a",
   "metadata": {},
   "source": [
    "**Next**: Exercises 12.5–12.9 (Part C) bend the dent deeper and watch goal programming and evolutionary methods handle it; AXIOM-12's frontier studio lets stakeholders drag the reference point live. Chapter 13 sends optimization to learn: machine learning. Solutions: IM Vol. II, Ch. 12."
   ]
  }
 ],
 "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
}
