{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3"
  },
  "language_info": {
   "name": "python"
  },
  "colab": {
   "provenance": []
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day 48: Chains, Forks & Colliders\n",
    "\n",
    "*Beginner to Ninja: Math for Causal Inference*\n",
    "\n",
    "Every path in a DAG is built from three junctions. Chains and forks transmit association unless you condition on their middle node; colliders block it unless you do. This asymmetry drives everything in Phase 4.\n",
    "\n",
    "**Learning outcomes**\n",
    "\n",
    "- Classify each three-node junction on a path as a chain, fork or collider.\n",
    "- Compute correlations in linear models by multiplying path coefficients.\n",
    "- Prove that conditioning on a chain or fork middle removes association while conditioning on a collider (or its descendant) creates it.\n",
    "- Recognise collider bias in hiring, hospital and birth-weight data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Theory\n",
    "\n",
    "### Three junctions\n",
    "\n",
    "Any path through a middle node $M$ looks like one of these:\n",
    "\n",
    "| Name | Shape | Unconditionally | Conditioning on $M$ |\n",
    "|---|---|---|---|\n",
    "| **Chain** (mediator) | $A \\to M \\to B$ | $A, B$ associated | association **blocked** |\n",
    "| **Fork** (confounder) | $A \\leftarrow M \\to B$ | $A, B$ associated | association **blocked** |\n",
    "| **Collider** | $A \\to M \\leftarrow B$ | $A, B$ **independent** | association **created** |\n",
    "\n",
    "Conditioning on a **descendant** of a collider also opens it, partially.\n",
    "\n",
    "### Intuition\n",
    "\n",
    "- **Chain:** job training raises skills, skills raise wages. Among workers with the same skills, training tells you nothing more about wages.\n",
    "- **Fork:** income raises both gym membership and health. Among people with the same income, gym membership and health are unrelated (in this story).\n",
    "- **Collider:** ability and connections both help land a job at a top firm. Among employees, a worker with weak connections must have had high ability to get in: the two become *negatively* related.\n",
    "\n",
    "### Linear path analysis\n",
    "\n",
    "Take standardised variables (mean 0, variance 1) in a linear model where each arrow has a coefficient. Sewall Wright's **path-tracing rule**: the correlation between two variables is the sum, over all paths **without colliders**, of the products of the coefficients along the path.\n",
    "\n",
    "Chain $Z \\xrightarrow{a} X \\xrightarrow{b} Y$: $\\operatorname{corr}(Z, Y) = ab$. Fork $Z \\xleftarrow{a} X \\xrightarrow{b} Y$: $\\operatorname{corr}(Z, Y) = ab$. Collider $Z \\to X \\leftarrow Y$: $\\operatorname{corr}(Z, Y) = 0$.\n",
    "\n",
    "### Conditioning in the Gaussian case\n",
    "\n",
    "For jointly normal variables, conditioning on $X$ leaves the covariance\n",
    "\n",
    "$$\n",
    "\\operatorname{Cov}(Z, Y \\mid X) = \\operatorname{Cov}(Z, Y) - \\frac{\\operatorname{Cov}(Z, X)\\operatorname{Cov}(X, Y)}{\\operatorname{Var}(X)},\n",
    "$$\n",
    "\n",
    "which is what a regression of $Y$ on $Z$ and $X$ estimates (Frisch–Waugh–Lovell, Day 28). For the collider $X = Z + Y + e$ the first term is 0 and the second is non-zero, so conditioning *creates* a covariance.\n",
    "\n",
    "### Ways of \"conditioning\"\n",
    "\n",
    "Conditioning happens whenever you stratify, add a variable to a regression, match on it, or **select the sample** on it: studying only hospital patients, only employed workers, only firms that survived, only people who answered a survey. Selection is conditioning you may not notice (Day 57).\n",
    "\n",
    "## Part 1 · Warm-up"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1 · Name the junction\n",
    "\n",
    "In the DAG $A \\to B \\to C$, $A \\to D \\leftarrow C$, $E \\to A$, $E \\to F$, classify: (a) $A, B, C$; (b) $A, D, C$; (c) $B, A, E$ (on the path $B \\leftarrow A \\leftarrow E$); (d) $A, E, F$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** (a) $A \\to B \\to C$: chain.\n",
    "\n",
    "**Step 2.** (b) $A \\to D \\leftarrow C$: collider at $D$.\n",
    "\n",
    "**Step 3.** (c) $B \\leftarrow A \\leftarrow E$: arrows run in one direction through $A$, so a chain (read backwards).\n",
    "\n",
    "**Step 4.** (d) $A \\leftarrow E \\to F$: fork at $E$.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2 · A chain's correlation\n",
    "\n",
    "Standardised variables follow $Z \\xrightarrow{0.5} X \\xrightarrow{0.6} Y$. Find $\\operatorname{corr}(Z, Y)$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** One path without colliders: $Z \\to X \\to Y$.\n",
    "\n",
    "**Step 2.** Multiply the coefficients: $0.5 \\times 0.6 = 0.30$.\n",
    "\n",
    "**Answer:** 0.30.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3 · A fork's correlation\n",
    "\n",
    "Standardised variables follow $Z \\xleftarrow{0.7} X \\xrightarrow{-0.4} Y$. Find $\\operatorname{corr}(Z, Y)$ and the correlation given $X$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** One path: $Z \\leftarrow X \\to Y$; product $0.7 \\times (-0.4) = -0.28$.\n",
    "\n",
    "**Step 2.** Given $X$, the fork is blocked: partial correlation 0.\n",
    "\n",
    "**Answer:** −0.28 unconditionally; 0 given $X$.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4 · A collider's correlation\n",
    "\n",
    "$Z$ and $Y$ are independent standard normals and $X = Z + Y$ (no noise). Find $\\operatorname{corr}(Z, Y)$ and $\\operatorname{corr}(Z, Y \\mid X)$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Unconditionally they are independent: correlation 0.\n",
    "\n",
    "**Step 2.** Given $X = x$, $Y = x - Z$ exactly.\n",
    "\n",
    "**Step 3.** So $Y$ is a decreasing linear function of $Z$: correlation −1.\n",
    "\n",
    "**Answer:** 0 and −1. Conditioning on a collider can create the strongest possible association.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5 · Open or blocked?\n",
    "\n",
    "For each path, say whether it transmits association: (a) $A \\to M \\to B$ given $M$; (b) $A \\to M \\leftarrow B$ given nothing; (c) $A \\to M \\leftarrow B$ given a child of $M$; (d) $A \\leftarrow M \\to B$ given nothing.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** (a) Chain, middle conditioned: blocked.\n",
    "\n",
    "**Step 2.** (b) Collider, not conditioned: blocked.\n",
    "\n",
    "**Step 3.** (c) Collider with a conditioned descendant: open.\n",
    "\n",
    "**Step 4.** (d) Fork, not conditioned: open.\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 2 · Proofs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 6 · The linear chain\n",
    "\n",
    "Let $X = aZ + e_X$ and $Y = bX + e_Y$, with $Z, e_X, e_Y$ independent, mean 0. Prove $\\operatorname{Cov}(Z, Y) = ab\\operatorname{Var}(Z)$ and $\\operatorname{Cov}(Z, Y \\mid X) = 0$ (in the partial-covariance sense).\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Substitute: $Y = abZ + be_X + e_Y$.\n",
    "\n",
    "**Step 2.** $\\operatorname{Cov}(Z, Y) = ab\\operatorname{Var}(Z)$, since $Z$ is independent of $e_X, e_Y$.\n",
    "\n",
    "**Step 3.** $\\operatorname{Cov}(Z, X) = a\\operatorname{Var}(Z)$ and $\\operatorname{Cov}(X, Y) = b\\operatorname{Var}(X)$.\n",
    "\n",
    "**Step 4.** Partial covariance:\n",
    "\n",
    "$$\n",
    "\\operatorname{Cov}(Z, Y) - \\frac{\\operatorname{Cov}(Z, X)\\operatorname{Cov}(X, Y)}{\\operatorname{Var}(X)} = ab\\operatorname{Var}(Z) - \\frac{a\\operatorname{Var}(Z)\\,b\\operatorname{Var}(X)}{\\operatorname{Var}(X)} = 0. \\quad \\blacksquare\n",
    "$$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 7 · The linear fork\n",
    "\n",
    "Let $Z = aX + e_Z$ and $Y = bX + e_Y$ with $X, e_Z, e_Y$ independent. Prove $\\operatorname{Cov}(Z, Y) = ab\\operatorname{Var}(X)$ and the partial covariance given $X$ is 0.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\operatorname{Cov}(Z, Y) = \\operatorname{Cov}(aX + e_Z, bX + e_Y) = ab\\operatorname{Var}(X)$.\n",
    "\n",
    "**Step 2.** $\\operatorname{Cov}(Z, X) = a\\operatorname{Var}(X)$ and $\\operatorname{Cov}(X, Y) = b\\operatorname{Var}(X)$.\n",
    "\n",
    "**Step 3.** Partial covariance: $ab\\operatorname{Var}(X) - \\dfrac{a\\operatorname{Var}(X)\\,b\\operatorname{Var}(X)}{\\operatorname{Var}(X)} = 0$. $\\blacksquare$\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 8 · Conditioning on a collider\n",
    "\n",
    "Let $Z, Y$ be independent $N(0, 1)$ and $X = Z + Y + e$ with $e \\sim N(0, \\sigma^2)$ independent. Prove that the partial correlation of $Z$ and $Y$ given $X$ is $-1/(1 + \\sigma^2)$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $\\operatorname{Var}(X) = 2 + \\sigma^2$, $\\operatorname{Cov}(Z, X) = \\operatorname{Cov}(Y, X) = 1$, $\\operatorname{Cov}(Z, Y) = 0$.\n",
    "\n",
    "**Step 2.** Partial covariance: $0 - \\dfrac{1 \\cdot 1}{2 + \\sigma^2} = -\\dfrac{1}{2 + \\sigma^2}$.\n",
    "\n",
    "**Step 3.** Partial variances: $\\operatorname{Var}(Z \\mid X) = \\operatorname{Var}(Y \\mid X) = 1 - \\dfrac{1}{2 + \\sigma^2} = \\dfrac{1 + \\sigma^2}{2 + \\sigma^2}$.\n",
    "\n",
    "**Step 4.** Partial correlation:\n",
    "\n",
    "$$\n",
    "\\frac{-1/(2 + \\sigma^2)}{(1 + \\sigma^2)/(2 + \\sigma^2)} = -\\frac{1}{1 + \\sigma^2}. \\quad \\blacksquare\n",
    "$$\n",
    "\n",
    "With $\\sigma^2 = 1$ it is −0.5; with no noise it is −1 (Exercise 4).\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 9 · Conditioning on a collider's descendant\n",
    "\n",
    "In Exercise 8 add $W = X + u$ with $u \\sim N(0, \\tau^2)$ independent. Prove the partial correlation of $Z$ and $Y$ given $W$ is $-1/(1 + \\sigma^2 + \\tau^2)$.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** $W = Z + Y + e + u$, so $\\operatorname{Var}(W) = 2 + \\sigma^2 + \\tau^2$ and $\\operatorname{Cov}(Z, W) = \\operatorname{Cov}(Y, W) = 1$.\n",
    "\n",
    "**Step 2.** This has exactly the form of Exercise 8 with noise variance $\\sigma^2 + \\tau^2$ in place of $\\sigma^2$.\n",
    "\n",
    "**Step 3.** So the partial correlation is $-1/(1 + \\sigma^2 + \\tau^2)$. $\\blacksquare$\n",
    "\n",
    "A noisy descendant opens the collider partially: weaker, but not zero.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 10 · Regression in a chain\n",
    "\n",
    "In the chain of Exercise 6, regress $Y$ on both $Z$ and $X$. Prove that the population coefficient on $Z$ is 0.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** By Frisch–Waugh–Lovell, the coefficient on $Z$ equals $\\operatorname{Cov}(\\tilde Z, Y)/\\operatorname{Var}(\\tilde Z)$, where $\\tilde Z$ is $Z$ residualised on $X$.\n",
    "\n",
    "**Step 2.** $\\operatorname{Cov}(\\tilde Z, Y)$ is the partial covariance of $Z$ and $Y$ given $X$.\n",
    "\n",
    "**Step 3.** By Exercise 6 it is 0, so the coefficient is 0. $\\blacksquare$ Controlling for a mediator removes the whole effect that passes through it.\n",
    "\n",
    "</details>\n",
    "\n",
    "## Part 3 · Applied"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 11 · Hiring at a top firm\n",
    "\n",
    "Applicants' ability $A$ and family connections $C$ are independent standard normals. A firm hires when $A + C > 1.5$. In simulation (code below), what share is hired, and what is $\\operatorname{corr}(A, C)$ among employees? Explain the HR department's finding that \"well-connected hires are less able\".\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Hiring is a collider: $A \\to \\text{Hired} \\leftarrow C$.\n",
    "\n",
    "**Step 2.** Studying employees conditions on it. Among those hired, low $C$ must be offset by high $A$ to pass the threshold.\n",
    "\n",
    "**Step 3.** The simulation gives about 14% hired and a correlation of about −0.68 among them (0 in the applicant pool).\n",
    "\n",
    "**Answer:** the negative relation is created by selection; it says nothing about whether connections reduce ability. The firm would see the same pattern even if the two were unrelated in the population.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 12 · The birth-weight paradox\n",
    "\n",
    "Maternal smoking $S$ (30% of mothers) and a serious birth defect $D$ (5%) are independent. Both cause low birth weight $L$: $P(L = 1 \\mid S, D)$ is 0.05 (neither), 0.15 (smoking only), 0.6 (defect only), 0.7 (both). Infant mortality is $P(M = 1 \\mid L, D) = 0.005 + 0.02L + 0.10D$; smoking affects mortality only through birth weight. Compare mortality for babies of smokers and non-smokers (a) overall and (b) among low-birth-weight babies.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Overall, $P(L = 1 \\mid S = 1) = 0.95(0.15) + 0.05(0.7) = 0.1775$ and $P(L = 1 \\mid S = 0) = 0.95(0.05) + 0.05(0.6) = 0.0775$.\n",
    "\n",
    "**Step 2.** Overall mortality: $S = 1$: $0.005 + 0.02(0.1775) + 0.10(0.05) = 0.01355$; $S = 0$: $0.005 + 0.02(0.0775) + 0.005 = 0.01155$. Smoking raises mortality.\n",
    "\n",
    "**Step 3.** Among low-birth-weight babies, use Bayes: $P(D = 1 \\mid L = 1, S = 1) = \\dfrac{0.05(0.7)}{0.05(0.7) + 0.95(0.15)} = \\dfrac{0.035}{0.1775} \\approx 0.197$.\n",
    "\n",
    "**Step 4.** $P(D = 1 \\mid L = 1, S = 0) = \\dfrac{0.05(0.6)}{0.05(0.6) + 0.95(0.05)} = \\dfrac{0.03}{0.0775} \\approx 0.387$.\n",
    "\n",
    "**Step 5.** Mortality among low-birth-weight babies: $S = 1$: $0.025 + 0.10(0.197) \\approx 0.0447$; $S = 0$: $0.025 + 0.10(0.387) \\approx 0.0637$.\n",
    "\n",
    "**Answer:** among low-birth-weight babies, those of smokers die *less* often. Low birth weight is a collider; a small baby of a non-smoker is more likely to have a defect. Smoking is harmful overall.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 13 · Controlling for a mediator\n",
    "\n",
    "In standardised form, job training $T \\xrightarrow{0.6} \\text{skills } S \\xrightarrow{0.5} \\text{wage } W$, with no direct arrow from $T$ to $W$. An analyst regresses wages on training \"controlling for skills\" and finds no effect. What is the total effect, and what went wrong?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** Total effect of a one-sd increase in $T$: $0.6 \\times 0.5 = 0.30$ sd of wages (path tracing).\n",
    "\n",
    "**Step 2.** Skills is the middle of a chain; conditioning on it blocks the only causal path (Exercise 10).\n",
    "\n",
    "**Answer:** the total effect is 0.30, but the regression with skills reports 0. Don't control for mediators when you want the total effect.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 14 · Gyms and health\n",
    "\n",
    "In standardised form, income $I \\xrightarrow{0.5}$ gym membership $G$ and $I \\xrightarrow{0.4}$ health $H$, with no arrow between $G$ and $H$. What correlation between gym membership and health will a survey find, with and without controlling for income?\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** One open path: the fork $G \\leftarrow I \\to H$.\n",
    "\n",
    "**Step 2.** $\\operatorname{corr}(G, H) = 0.5 \\times 0.4 = 0.20$.\n",
    "\n",
    "**Step 3.** Given income, the fork is blocked: partial correlation 0.\n",
    "\n",
    "**Answer:** 0.20 without control, 0 with it. Here the confounder must be controlled.\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 15 · Which to control?\n",
    "\n",
    "For each study, identify the junction and say whether to condition on the middle variable: (a) effect of a cash transfer on child schooling, middle variable household consumption; (b) effect of air pollution on asthma visits, middle variable temperature (affects both); (c) effect of a new drug on recovery, studying only patients who completed follow-up, when both side effects of the drug and poor health cause dropout.\n",
    "\n",
    "<details><summary>Show solution</summary>\n",
    "\n",
    "**Step 1.** (a) Transfer $\\to$ consumption $\\to$ schooling: chain. Do not condition if you want the total effect.\n",
    "\n",
    "**Step 2.** (b) Pollution $\\leftarrow$ temperature $\\to$ asthma: fork (confounder). Condition on temperature.\n",
    "\n",
    "**Step 3.** (c) Drug $\\to$ dropout $\\leftarrow$ poor health $\\to$ recovery: dropout is a collider.\n",
    "\n",
    "**Step 4.** Analysing completers conditions on it and opens a non-causal path from drug to recovery.\n",
    "\n",
    "**Answer:** don't condition in (a) or (c); do condition in (b). For (c), analyse everyone randomised (intention to treat) with methods for missing outcomes (Day 14).\n",
    "\n",
    "</details>\n",
    "\n",
    "## Verify in Python"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Your work:*"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def pcorr(a, b, c):\n",
    "    \"\"\"Partial correlation of a and b given c (residualise both on c).\"\"\"\n",
    "    C = np.column_stack([np.ones_like(c), c])\n",
    "    ra = a - C @ np.linalg.lstsq(C, a, rcond=None)[0]\n",
    "    rb = b - C @ np.linalg.lstsq(C, b, rcond=None)[0]\n",
    "    return np.corrcoef(ra, rb)[0, 1]\n",
    "\n",
    "rng = np.random.default_rng(48)\n",
    "n = 1_000_000\n",
    "# chain, fork and collider with standardised coefficients\n",
    "Z = rng.normal(size=n); X = .5 * Z + np.sqrt(1 - .25) * rng.normal(size=n); Y = .6 * X + np.sqrt(1 - .36) * rng.normal(size=n)\n",
    "print(f\"chain:    corr {np.corrcoef(Z, Y)[0, 1]:.3f} (0.30)  given X {pcorr(Z, Y, X):.3f}\")\n",
    "X = rng.normal(size=n); Z = .7 * X + np.sqrt(1 - .49) * rng.normal(size=n); Y = -.4 * X + np.sqrt(1 - .16) * rng.normal(size=n)\n",
    "print(f\"fork:     corr {np.corrcoef(Z, Y)[0, 1]:.3f} (-0.28) given X {pcorr(Z, Y, X):.3f}\")\n",
    "Z = rng.normal(size=n); Y = rng.normal(size=n); X = Z + Y + rng.normal(size=n); W = X + rng.normal(size=n)\n",
    "print(f\"collider: corr {np.corrcoef(Z, Y)[0, 1]:.3f}  given X {pcorr(Z, Y, X):.3f} (-1/2)  given W {pcorr(Z, Y, W):.3f} (-1/3)\")\n",
    "\n",
    "# Exercise 11: hiring\n",
    "A = rng.normal(size=n); C = rng.normal(size=n); hired = A + C > 1.5\n",
    "print(f\"hired {hired.mean():.3f}; corr(A, C) all {np.corrcoef(A, C)[0, 1]:.3f}, hired {np.corrcoef(A[hired], C[hired])[0, 1]:.3f}\")\n",
    "\n",
    "# Exercise 12: birth-weight paradox (exact)\n",
    "pL = {(0, 0): .05, (1, 0): .15, (0, 1): .6, (1, 1): .7}          # key (s, d)\n",
    "mort = lambda l, d: .005 + .02 * l + .10 * d\n",
    "for s in (0, 1):\n",
    "    overall = sum((.05 if d else .95) * (pL[s, d] * mort(1, d) + (1 - pL[s, d]) * mort(0, d)) for d in (0, 1))\n",
    "    pd = .05 * pL[s, 1] / (.05 * pL[s, 1] + .95 * pL[s, 0])\n",
    "    print(f\"smoker={s}: mortality overall {overall:.5f}; P(defect|LBW) {pd:.3f}; mortality | LBW {mort(1, 0) + .10 * pd:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Key takeaways\n",
    "\n",
    "- Chains and forks transmit association; conditioning on their middle node blocks it.\n",
    "- Colliders block association; conditioning on them, or on their descendants, or selecting the sample on them, creates it.\n",
    "- In linear models, correlations are sums of products of path coefficients over collider-free paths."
   ]
  }
 ]
}