Every June, as the monsoon rolls into Mumbai, two things spike together across the city's traffic-sensor logs: the number of open umbrellas reported near railway stations, and the average commute delay in minutes. Pull the correlation coefficient between "umbrellas counted" and "commute delay" over three years of data and you will get a strong positive number, easily above 0.7. A naive data-mining project would flag this as an actionable insight and might even suggest, absurdly, that confiscating umbrellas would speed up traffic. The mistake is obvious once stated: rainfall causes both. But here is the harder question this chapter actually answers — if you were only handed the numbers, with no prior knowledge that rain exists, could you have figured out, algorithmically, that "umbrellas" and "commute delay" are not causing each other, but are both effects of a hidden third cause? And could you have told a different, superficially identical-looking pattern apart — one where a variable genuinely does cause another in a chain? This is the subject of causal discovery: turning "X and Y are correlated" into "here is the actual arrow-diagram of who causes whom," using nothing but data and a small set of provably correct rules.
You have almost certainly heard the slogan "correlation is not causation." That slogan is true but useless by itself — it tells you what you cannot conclude, not what you can. Causal discovery is the field that replaces the slogan with a precise, checkable theory: given a table of observations (and, when available, data from deliberate interventions), which causal structures are consistent with what you see, and which are ruled out? The theory was built mainly by the computer scientist and philosopher Judea Pearl, whose 1988–2000s work on causal graphs and the "do-calculus" earned him the ACM A.M. Turing Award in 2011 — the same award computer science gives for its most fundamental contributions. This is not a settled, textbook-only topic; it is an active research area with direct applications in Indian agri-tech (does a subsidy scheme cause yield increases, or do both correlate with rainfall?), public health (does a vaccine campaign cause a case-count drop, or did the season change?), and economics. We are going to build the theory from first principles.
Causal graphs: making "causes" a mathematical object
A causal graph (formally, a Directed Acyclic Graph or DAG) is a picture with two ingredients: a set of nodes, one per variable you care about, and a set of directed edges, where an arrow A → B means "A is a direct cause of B" — changing A, holding everything else in the system fixed, changes the distribution of B. "Acyclic" means no chain of arrows can loop back to where it started: causes cannot be their own effects, because that would make time run in a circle. Behind every causal graph sits a Structural Causal Model (SCM): each variable is written as a function of its direct causes (its "parents" in the graph) plus its own independent randomness. For our monsoon example:
Rain = U_rain (exogenous: weather system, unexplained by our model)
Umbrellas = f_U(Rain, U_umb) (more rain -> more umbrellas out, plus noise)
Delay = f_D(Rain, U_delay) (more rain -> more delay, plus noise)
Notice Umbrellas does not appear in the equation for Delay, and Delay does not appear in the equation for Umbrellas. That absence is the entire causal claim: neither variable is a direct cause of the other. The graph for this SCM is Rain → Umbrellas and Rain → Delay — a single cause with two effects. This structure has a name, and it is the first of three atomic "shapes" that every causal graph, no matter how large, is built out of.
The three atomic structures
Any three connected variables X, Y, Z in a causal DAG must form one of exactly three local patterns. Understanding how correlation flows through each one — and does not flow through the others — is the single most load-bearing idea in this chapter, because the entire causal-discovery algorithm later in the chapter is just "test which of these three patterns is present, over and over, across a whole graph."
- Chain: X → Z → Y. Z is a mediator. X affects Y only by first affecting Z. Example: Rainfall → Waterlogged Roads → Late to Office.
- Fork: X ← Z → Y. Z is a common cause (confounder). Example: Rainfall → Umbrellas and Rainfall → Delay — this is our monsoon example, with Z = Rain playing the fork role, and "Umbrellas"/"Delay" playing the roles of X and Y.
- Collider: X → Z ← Y. Z is a common effect. X and Y are two independent causes that both influence Z.
Now the crucial question: in each pattern, are X and Y statistically dependent (correlated), and does that change if you condition on Z — that is, if you restrict attention to a fixed value of Z, the way "look only at days when Z=rainy" restricts a dataset?
For a chain X → Z → Y: unconditionally, X and Y are dependent, because information flows X → Z → Y like a relay. But if you fix Z (condition on it), you have cut the relay in the middle — knowing X tells you nothing more about Y once Z is already known, because everything X could tell you about Y, it tells you through Z. Formally, X ⊥ Y | Z (X is independent of Y given Z).
For a fork X ← Z → Y: unconditionally, X and Y are dependent — this is exactly the spurious-correlation case: Rain makes Umbrellas and Delay move together even though neither causes the other. But condition on Z (fix the rainfall, e.g. look only at rainy days), and the shared cause is held constant — whatever variation is left in Umbrellas and Delay on rainy days alone comes from independent noise, so they become independent. Again X ⊥ Y | Z.
For a collider X → Z ← Y, the rule flips — and this is the fact that separates a real understanding of causal graphs from a superficial one. Unconditionally, X and Y are independent: two unrelated causes of the same effect do not, by default, tell you anything about each other. But condition on Z, and you manufacture a dependency between X and Y that was never there causally. This is called explaining away or collider bias (also known as Berkson's paradox). Here is the intuition with numbers, using a scholarship scheme: suppose a college offers a merit scholarship to any student who is either exceptionally talented (X, base rate 10%) or exceptionally hardworking (Y, base rate 10%), and these two traits are, before you know anything else, completely independent of each other.
# Collider structure (a "v-structure"): X (talented) -> Z (scholarship) <- Y (hardworking)
# X and Y are independent causes; Z = 1 whenever X=1 OR Y=1
p_x1, p_y1 = 0.10, 0.10 # marginal probabilities, independent a priori
p_z1 = 1 - (1 - p_x1) * (1 - p_y1) # P(Z=1) = P(X=1 or Y=1)
p_x1_given_z1 = p_x1 / p_z1 # Bayes' theorem: X=1 always implies Z=1
p_x1_given_z1_and_y0 = 1.0 # if Z=1 and Y=0, X=1 is forced
print("P(X=1) =", round(p_x1, 4))
print("P(X=1 | Z=1) =", round(p_x1_given_z1, 4))
print("P(X=1 | Z=1, Y=0) =", round(p_x1_given_z1_and_y0, 4))
# Output: 0.1 -> 0.5263 -> 1.0
# Belief about X keeps changing as we learn more about Y, but ONLY because
# we already conditioned on the collider Z. That shift is collider bias.
Trace the logic: P(Z=1) = 1 − (0.9)(0.9) = 0.19. Since X=1 forces Z=1, P(X=1, Z=1) = P(X=1) = 0.10, so by Bayes' theorem P(X=1 | Z=1) = 0.10 / 0.19 ≈ 0.5263 — already a jump from the 10% base rate, purely from knowing the student got the scholarship. Now suppose you additionally learn the student is not hardworking (Y=0). Since a scholarship requires talent OR hard work, and hard work is ruled out, talent is now certain: P(X=1 | Z=1, Y=0) = 1.0. Learning about Y changed your belief about X — even though X and Y are, causally, completely unrelated. That is what "conditioning on a collider opens the path" means in concrete numbers.
Diagram: chain, fork, and collider side by side
Read the collider panel carefully — it is the single most important and most misunderstood fact in this entire subject, precisely because it is the mirror image of what chains and forks do. In a chain or a fork, the path starts open and conditioning on the middle node blocks it. In a collider, the path starts blocked and conditioning on the middle node (or on anything downstream of it) opens it. If you remember only one asymmetry from this chapter, it should be this one, because it is exactly the asymmetry that makes causal discovery from pure observation possible at all — the next two sections show why.
d-separation: the general rule for whole graphs
Real causal graphs have more than three nodes, and a pair of variables can be connected by several different paths at once. d-separation ("d" for "directional") is the rule that generalizes the three atomic cases to an entire graph: X and Y are d-separated given a conditioning set S if every path between them is blocked, where a path is blocked if it contains at least one non-collider node that is in S, or at least one collider node such that neither the collider nor any of its descendants is in S. If X and Y are d-separated given S, the graph predicts X ⊥ Y | S — and this is the only kind of prediction a DAG makes that data can check.
Work through a concrete four-variable example. Rainfall (R) causes both Traffic (T) and Wet Ground (W); Traffic in turn causes students arriving Late to school (L):
Are W (wet ground) and L (late to school) d-separated by S = {T}? There is exactly one path between them: L ← T ← R → W. Walking along it, T sits between L and R with edges T→L and R→T, both pointing "forward" along the path — T is a chain node here, and it is in S, so it blocks the path. R sits between T and W with edges R→T and R→W both pointing away from R — R is a fork node on this path, but it is not in S, so that alone would leave the path open; however a path is blocked if any node on it is a blocking node, and T already blocks it. So W ⊥ L | T: once you know today's traffic level, knowing whether the ground is wet gives you no further information about whether a student is late. This is a real, checkable, falsifiable prediction — you could go collect three months of data and test it.
Now extend the graph one more step to see the collider rule do real work. Suppose Exam Performance (E) is caused independently by two things: whether a student arrived Late (L) and how well they Prepared (P) beforehand — L → E ← P, a fresh collider. Unconditionally, L and P are d-separated (arriving late and having studied hard are independent facts about a student), so L ⊥ P. But now condition on E — say, you only look at students who scored poorly. Within that group, L and P become dependent: if you learn a particular poor-scoring student was not late, explaining-away reasoning kicks in and raises your estimate that they simply hadn't prepared, and vice versa. A teacher reasoning informally does this kind of explaining-away instinctively; d-separation is what makes it exact and lets you check it against real gradebook data.
Markov equivalence: the wall observational data hits
Here is the uncomfortable fact that motivates everything past this point. Take the fork X ← Z → Y and the chain X ← Z ← Y (i.e. Y → Z → X) and the chain X → Z → Y. All three imply the exact same independence pattern: X and Y are dependent unconditionally, and X ⊥ Y | Z. A conditional-independence test run on data cannot tell these three DAGs apart — they are said to belong to the same Markov equivalence class. Observational data, no matter how much of it you collect, can only ever narrow the true causal graph down to an equivalence class, not to one specific DAG, unless a collider is involved. A collider X → Z ← Y is the one pattern among the three whose independence signature (X ⊥ Y unconditionally, dependent given Z) is not shared by any relabelling of a chain or fork — it is uniquely identifiable from data alone. This asymmetry is the entire reason colliders got a full paragraph of emphasis above: they are the only lever purely observational causal discovery has.
The PC algorithm: discovering structure from conditional independence tests
Put d-separation and Markov equivalence together and you get an actual algorithm — the PC algorithm (named after its inventors, Peter Spirtes and Clark Glymour), a foundational method in constraint-based causal discovery. It has two phases.
Phase 1 — skeleton discovery. Start with a complete undirected graph connecting every pair of variables. For each pair, search for some conditioning set that makes them independent; if you find one, delete the edge between them and record the conditioning set as their "separating set." What survives is the graph's skeleton — which pairs of variables are directly connected, with directions not yet decided.
Phase 2 — orientation. For every unshielded triple A—B—C in the skeleton (A and C both connected to B, but not to each other), check whether B was in the separating set that removed the A–C edge. If B was not in that separating set, the triple must be a collider: orient it A→B←C (this is exactly the identifiability fact from the previous section). Any remaining undirected edges are then oriented, where possible, using a small set of purely logical follow-up rules (Meek's rules) that prevent creating a new collider or a cycle — but many edges may still be left undirected if there is no such forcing.
Run this by hand on the Rain/Traffic/Wet-ground/Late graph. Phase 1: test each pair. R,T are dependent under every conditioning set tried → keep edge R–T. R,W dependent throughout → keep R–W. T,L dependent throughout → keep T–L. T,W: dependent unconditionally, but independent once you condition on R (this is the fork rule) → delete edge T–W, record separating set {R}. R,L: dependent unconditionally, but independent once you condition on T (the chain rule) → delete edge R–L, record separating set {T}. W,L: dependent unconditionally, independent given R → delete edge W–L, separating set {R}. The surviving skeleton is exactly R–T, R–W, T–L — the algorithm has correctly recovered which variables are directly connected, using nothing but independence tests.
Phase 2: check the unshielded triple T–R–W. Was R (the middle node) in the separating set that removed T–W? Yes, {R} — so this is not a collider; R is a chain or fork node here, and PC leaves this triple's directions undetermined. Check the unshielded triple R–T–L. Was T in the separating set that removed R–L? Yes, {T} — again not a collider, directions undetermined. There are no unshielded triples where the middle node was excluded from the separating set, so zero colliders are found, and the PC algorithm terminates having recovered the correct skeleton but unable to orient a single edge. This is Markov equivalence made concrete: the true graph (R→T→L with R→W) is only one of several DAGs consistent with exactly this skeleton and these independencies. Purely observational data has hit its wall.
Breaking the wall: interventions and the do-operator
An intervention is different from conditioning, and confusing the two is the second major misconception this chapter needs to correct. Conditioning on X=x — writing P(Y | X=x) — means "restrict attention to the rows of your dataset where X happened to equal x," leaving every causal arrow in the graph untouched, including arrows pointing into X from its own causes. Intervening — writing P(Y | do(X=x)), Pearl's do-operator — means "reach into the system and force X to equal x by fiat," which is graphically equivalent to deleting every arrow that points into X (since X's value no longer depends on its usual causes) and then reading off probabilities in this surgically modified graph. Conditioning asks "what do we learn about Y from observing that X happened to be x." Intervention asks "what would Y become if we made X be x." A randomized controlled trial is precisely how experimenters implement do(X=x) in the real world: randomizing treatment assignment severs the link between treatment and any of its natural causes (including confounders), which is exactly what graph surgery does on paper.
This gives a direct way to finish what the PC algorithm above left unresolved. We know R–T is an edge but not its direction. Suppose city traffic police, independent of the weather, randomly close a set of roads on some days — this is do(T=t): traffic congestion is now forced by fiat, its usual causal parents (rainfall, if any existed) are surgically disconnected. After this intervention, test whether R and T are still correlated. If the true direction were R→T (rain causes traffic), the intervention on T severs exactly that edge, so post-intervention R and T become independent — the correlation you used to see should vanish. If instead the true direction were T→R, intervening on T does not touch any edge pointing into T's effects, so T (now experimenter-controlled) and its downstream effect would still move together after the intervention. In our real scenario the correlation would indeed vanish under do(T=t), confirming R→T and not the reverse — this is how a targeted, real-world intervention resolves a direction that no amount of passive observation could.
Common misconception, corrected explicitly
The single most common error students make after learning d-separation is assuming "conditioning on more variables can only help isolate the true causal effect — control for everything you have data on." This is false, and the collider section above is the proof: conditioning on a collider, or on any variable downstream of a collider, manufactures a spurious association between two variables that are genuinely causally unrelated. A real-world version of this mistake, sometimes called "selection bias" in statistics, happens whenever a dataset is built by selecting on an outcome that is itself a common effect — for example, studying only college applicants who were admitted (admission is a collider of test score and extracurriculars) will make test score and extracurriculars look negatively correlated in that admitted-only sample, even if they are unrelated in the general population, purely because both being weak simultaneously makes admission unlikely, so the surviving cases skew toward "strong in one, weak in the other." Before conditioning on any variable in an applied causal-inference task, the correct question is never "do I have this data," it is "what type of node is this in the causal graph" — mediator, confounder, or collider — because the three types require opposite actions.
Exam relevance for Indian students
The probability machinery underneath every rule in this chapter — conditional probability, independence of events, and Bayes' theorem — is CBSE Class 12 syllabus content (NCERT Chapter on Probability), so every d-separation and collider-bias calculation above is, mechanically, a Bayes'-theorem problem in disguise; practicing them sharpens exactly the conditional-probability fluency that JEE Main/Advanced and BITSAT probability questions test. The graph-theoretic side (DAGs, paths, skeletons) draws on the same graph vocabulary tested in discrete mathematics for GATE's AI/ML-adjacent papers. Causal discovery itself is not yet a fixture of any Indian board or entrance syllabus — it is genuine current research territory, which is exactly the kind of topic KVPY-style research-aptitude interviews and science-olympiad extended-response questions reward students for being able to reason about from first principles rather than recall.
Check your understanding
- In the SCM Rain = U_rain; Umbrellas = f(Rain, U); Delay = g(Rain, U'), draw the DAG and name the structure connecting Umbrellas and Delay through Rain.
Answer: a fork, Umbrellas ← Rain → Delay; Umbrellas and Delay are dependent unconditionally and independent given Rain. - A hospital records Illness Severity (S) and Hospital Admission (A), where A is caused by both S and Insurance Coverage (I): S → A ← I. Among admitted patients only, would you expect Severity and Insurance Coverage to appear correlated, even if they are unrelated in the general population? Why?
Answer: yes — A is a collider, and the "admitted patients only" dataset is exactly conditioning on that collider, which opens a spurious path between S and I (explaining away: mild severity among the admitted suggests strong insurance drove admission, and vice versa). - Run the PC algorithm's Phase 1 by hand on a triangle graph where every pair of three variables A, B, C remains dependent under every conditioning set you try. What skeleton and what orientation does Phase 2 produce?
Answer: no edge is ever removed (no separating set exists for any pair), so the skeleton is the complete triangle A–B–C, and since PC only orients unshielded triples (A and C not adjacent), and here every pair is adjacent, there are no unshielded triples to test — Phase 2 orients nothing. - For the Rain/Traffic/Wet-ground/Late graph in this chapter, is Rain d-separated from Late given the empty set (no conditioning)? Given {T}?
Answer: not d-separated given the empty set (the chain R→T→L is a fully open path); d-separated given {T}, since T is a chain node on the only path and conditioning on it blocks that path. - Explain, in do-notation, the difference between P(Delay | Umbrellas = many) and P(Delay | do(Umbrellas = many)) for the monsoon graph, and state which one government traffic planners should actually care about if they are deciding whether to hand out free umbrellas to reduce delay.
Answer: P(Delay | Umbrellas=many) reflects the observational correlation driven by the Rain confounder and would be large; P(Delay | do(Umbrellas=many)) surgically removes Rain's influence on Umbrellas and reflects the true causal effect of umbrella distribution alone, which — since Umbrellas has no causal edge into Delay in this graph — would show no effect. Planners should care about the do-version; acting on the observational version would lead them to (uselessly) hand out umbrellas expecting shorter commutes.
Summary
A causal graph turns "X causes Y" into a directed edge in a DAG, backed by a structural causal model where each variable is a function of its parents plus independent noise. Every local pattern in such a graph reduces to a chain (X→Z→Y), a fork (X←Z→Y), or a collider (X→Z←Y), and these three behave asymmetrically: chains and forks are open paths that conditioning on the middle node blocks, while a collider is a blocked path that conditioning on the middle node (or its descendants) opens — this single asymmetry is what makes any causal discovery from passive data possible at all. d-separation generalizes these three rules to whole graphs, predicting exactly which conditional independencies must hold if a candidate DAG is correct — predictions you can test against real data. Because chains and forks are statistically indistinguishable from each other (Markov equivalence), the PC algorithm can only ever recover a graph's skeleton plus the direction of edges forced by discovered colliders from observational data alone; the rest stays genuinely undetermined until you bring in interventions, formalized by Pearl's do-operator, which surgically remove incoming edges and let you test causal direction directly — the graph-theoretic version of what a randomized controlled trial does in the real world. The most consequential misconception to unlearn is that conditioning on more variables is always safer: conditioning on a collider fabricates correlation between causes that are, in truth, entirely independent.
Think About It
Think about this: How would you explain causal discovery: learning causal graphs from observational and interventional data to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.
Practice Exercises
Now it is time to practice! Complete these challenges to solidify your understanding:
- Exercise 1: Write a short program that demonstrates the core concept from this chapter. Test it with at least 3 different inputs.
- Exercise 2: Find a real-world example where causal discovery: learning causal graphs from observational and interventional data is used in an Indian company (like TCS, Infosys, Flipkart, or ISRO). Write a paragraph explaining the connection.
- Exercise 3: Create a mind-map connecting causal discovery: learning causal graphs from observational and interventional data to at least 3 other topics you have studied.