{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5a1f672e",
   "metadata": {},
   "source": [
    "# DCT Laboratory — Volume I, Chapter 3\n",
    "## Mathematical Foundations\n",
    "**Seed `26103`** · Companion to the chapter and AXIOM Module **AXIOM-03**\n",
    "\n",
    "Three foundations, made numerical: **distances between enterprise states** (which\n",
    "norm you choose changes which peer is \\\"closer\\\"), **operators and composition**\n",
    "(transformations as mappings, $T_2 \\circ T_1$), and the **unit-equivariance** of the\n",
    "weighted metric — the proposition that makes cross-unit comparison legitimate.\n",
    "Mirrored in `DCT_V1_Ch03_Lab.xlsx`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0d6e57b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:46.917082Z",
     "iopub.status.busy": "2026-07-13T21:47:46.916894Z",
     "iopub.status.idle": "2026-07-13T21:47:47.379744Z",
     "shell.execute_reply": "2026-07-13T21:47:47.378612Z"
    }
   },
   "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 = 26103\n",
    "X0 = np.array([100.0, 3.2, 62.0, 41.0, 68.0, 9.5, 55.0, 17.5])  # Meridian (Ch. 1)\n",
    "YA = np.array([ 92.0, 2.6, 70.0, 55.0, 71.0, 11.0, 48.0, 14.0])  # peer A\n",
    "YB = np.array([118.0, 4.1, 55.0, 30.0, 63.0,  7.5, 66.0, 22.0])  # peer B\n",
    "W  = np.array([0.01, 1.0, 0.02, 0.02, 0.02, 0.10, 0.02, 0.05])   # weights (unit-aware)\n",
    "\n",
    "def d1(x,y):  return float(np.abs(x-y).sum())\n",
    "def d2(x,y):  return float(np.sqrt(((x-y)**2).sum()))\n",
    "def dinf(x,y):return float(np.abs(x-y).max())\n",
    "def dW(x,y,w=W): return float(np.sqrt(((w*(x-y))**2).sum()))\n",
    "\n",
    "# Operators: T1 = mild digital push, T2 = deleveraging; composition T2∘T1\n",
    "T1 = np.eye(8); T1[3,3]=1.15; T1[0,0]=0.96; T1[0,3]=-0.05    # tech up, liquidity funds it\n",
    "T2 = np.eye(8); T2[1,1]=0.85; T2[0,1]=1.5                    # leverage down, cash from sale\n",
    "\n",
    "def reference_values():\n",
    "    v = T2 @ (T1 @ X0)\n",
    "    # unit change: x1 in $bn -> $mm (x1000), x8 % -> fraction (/100)\n",
    "    V = np.eye(8); V[0,0]=1000.0; V[7,7]=0.01\n",
    "    Winv = W @ np.linalg.inv(V)  # contravariant transform (diag)\n",
    "    dw_before = dW(X0, YA)\n",
    "    dw_after  = float(np.sqrt(((np.diag(Winv) @ (V@X0 - V@YA))**2).sum()))\n",
    "    return {\n",
    "        \"d1_x0_yA\":  round(d1(X0,YA),4),  \"d2_x0_yA\":  round(d2(X0,YA),4),\n",
    "        \"dinf_x0_yA\":round(dinf(X0,YA),4),\"dW_x0_yA\":  round(dw_before,4),\n",
    "        \"d2_x0_yB\":  round(d2(X0,YB),4),\n",
    "        \"T1x0_tech\": round(float((T1@X0)[3]),4),\n",
    "        \"T2T1x0_liquidity\": round(float(v[0]),4),\n",
    "        \"dW_unit_equivariance_gap\": round(abs(dw_before-dw_after),6),\n",
    "    }\n",
    "if __name__ == \"__main__\":\n",
    "    [print(f\"{k:28s} {v}\") for k,v in reference_values().items()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6719789c",
   "metadata": {},
   "source": [
    "## Panel 1 — Which peer is closer? It depends on the norm\n",
    "Meridian $\\mathbf{x}_0$ against peers A and B under $d_1$, $d_2$, $d_\\infty$, and the\n",
    "weighted $d_W$. Unweighted norms are dominated by the large-unit coordinates\n",
    "(liquidity); the weighted metric is the defensible one — Definition (Norm) +\n",
    "Proposition (Weighted Metrics and Unit Consistency)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8cd53aa5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:47.381654Z",
     "iopub.status.busy": "2026-07-13T21:47:47.381351Z",
     "iopub.status.idle": "2026-07-13T21:47:47.387405Z",
     "shell.execute_reply": "2026-07-13T21:47:47.386544Z"
    }
   },
   "outputs": [],
   "source": [
    "rows = [(\"d1\",d1),(\"d2\",d2),(\"d_inf\",dinf),(\"d_W (weighted)\",dW)]\n",
    "print(f\"{'metric':16s} {'x0 ↔ peer A':>12s} {'x0 ↔ peer B':>12s}   closer\")\n",
    "for nm,f in rows:\n",
    "    a,b = f(X0,YA), f(X0,YB)\n",
    "    print(f\"{nm:16s} {a:12.4f} {b:12.4f}   {'A' if a<b else 'B'}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9c9650c",
   "metadata": {},
   "source": [
    "## Panel 2 — Unit balls: the geometry of \\\"close\\\"\n",
    "The unit balls of $\\ell_1$, $\\ell_2$, $\\ell_\\infty$ in the $(x_4, x_5)$ plane, centered\n",
    "at Meridian. Same radius, three different sets of \\\"similar enterprises.\\\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "872f00d3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:47.389597Z",
     "iopub.status.busy": "2026-07-13T21:47:47.388897Z",
     "iopub.status.idle": "2026-07-13T21:47:47.697477Z",
     "shell.execute_reply": "2026-07-13T21:47:47.696378Z"
    }
   },
   "outputs": [],
   "source": [
    "th = np.linspace(0,2*np.pi,400)\n",
    "fig,ax = plt.subplots(figsize=(5.6,5.6))\n",
    "r=6\n",
    "ax.plot(X0[3]+r*np.cos(th), X0[4]+r*np.sin(th), color=\"#C8A24B\", lw=2, label=\"$\\\\ell_2$\")\n",
    "sq=np.array([[1,1],[-1,1],[-1,-1],[1,-1],[1,1]])*r\n",
    "ax.plot(X0[3]+sq[:,0], X0[4]+sq[:,1], color=\"#1B6B52\", lw=2, label=\"$\\\\ell_\\\\infty$\")\n",
    "di=np.array([[1,0],[0,1],[-1,0],[0,-1],[1,0]])*r\n",
    "ax.plot(X0[3]+di[:,0], X0[4]+di[:,1], color=\"#8A8F8B\", lw=2, label=\"$\\\\ell_1$\")\n",
    "ax.scatter([X0[3]],[X0[4]],c=\"k\",zorder=5)\n",
    "ax.set(xlabel=\"$x_4$ technology\", ylabel=\"$x_5$ efficiency\", title=\"Three unit balls, one center\", aspect=\"equal\")\n",
    "ax.legend(frameon=False); ax.grid(alpha=.25); plt.tight_layout(); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3982a41c",
   "metadata": {},
   "source": [
    "## Panel 3 — Operators and composition\n",
    "$T_1$ (digital push: tech ×1.15, funded from liquidity) then $T_2$ (deleveraging:\n",
    "leverage ×0.85, sale proceeds to cash). Composition is matrix multiplication;\n",
    "order matters, and feasibility chains through domains (Prop.: Operator\n",
    "Composition and Feasibility Chaining)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe496f8c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:47.699767Z",
     "iopub.status.busy": "2026-07-13T21:47:47.699062Z",
     "iopub.status.idle": "2026-07-13T21:47:47.706014Z",
     "shell.execute_reply": "2026-07-13T21:47:47.705121Z"
    }
   },
   "outputs": [],
   "source": [
    "x1 = T1@X0; x2 = T2@x1\n",
    "print(\"x0          :\", np.round(X0,2))\n",
    "print(\"T1 x0       :\", np.round(x1,2))\n",
    "print(\"T2 T1 x0    :\", np.round(x2,2))\n",
    "print(\"\\ntech after T1      :\", round(float(x1[3]),4))\n",
    "print(\"liquidity after T2T1:\", round(float(x2[0]),4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74df4eb3",
   "metadata": {},
   "source": [
    "## Panel 4 — Unit equivariance, verified numerically\n",
    "Change units ($x_1$: \\$bn → \\$mm; $x_8$: % → fraction) via $V$; transform the\n",
    "weights contravariantly ($W \\mapsto W V^{-1}$); the weighted distance is **unchanged**\n",
    "— the conclusion is invariant to the representation, which is what lets two\n",
    "analysts with different unit conventions agree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "979c3dda",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:47.707931Z",
     "iopub.status.busy": "2026-07-13T21:47:47.707753Z",
     "iopub.status.idle": "2026-07-13T21:47:47.713747Z",
     "shell.execute_reply": "2026-07-13T21:47:47.712685Z"
    }
   },
   "outputs": [],
   "source": [
    "V = np.eye(8); V[0,0]=1000.0; V[7,7]=0.01\n",
    "Winv = W @ np.linalg.inv(V)\n",
    "before = dW(X0,YA)\n",
    "after  = float(np.sqrt(((np.diag(Winv)@(V@X0 - V@YA))**2).sum()))\n",
    "print(\"d_W before unit change:\", round(before,6))\n",
    "print(\"d_W after  unit change:\", round(after,6))\n",
    "print(\"gap:\", abs(before-after))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea4ed7a8",
   "metadata": {},
   "source": [
    "## Validation — agrees with `DCT_V1_Ch03_Lab.xlsx`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5662dac4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-07-13T21:47:47.715340Z",
     "iopub.status.busy": "2026-07-13T21:47:47.715157Z",
     "iopub.status.idle": "2026-07-13T21:47:47.720650Z",
     "shell.execute_reply": "2026-07-13T21:47:47.719685Z"
    }
   },
   "outputs": [],
   "source": [
    "ref = reference_values()\n",
    "expected = {\"d1_x0_yA\":45.6,\"d2_x0_yA\":19.9213,\"dinf_x0_yA\":14.0,\"dW_x0_yA\":0.7394,\n",
    " \"d2_x0_yB\":25.7888,\"T1x0_tech\":47.15,\"T2T1x0_liquidity\":98.75,\"dW_unit_equivariance_gap\":0.0}\n",
    "for k,v in expected.items():\n",
    "    assert abs(ref[k]-v)<5e-4, f\"MISMATCH {k}\"\n",
    "    print(f\"PASS  {k:28s} {ref[k]}\")\n",
    "print(\"\\nAll checkpoints agree — seed 26103.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a4f58a0",
   "metadata": {},
   "source": [
    "**Next**: Exercises 3.9–3.12 (Part C); AXIOM-03's norm explorer animates Panel 2. Solutions: IM Ch. 3."
   ]
  }
 ],
 "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
}
