Making a model travel · step 2 of 6
Ask the graph about the population
Is a difference between two populations a difference that matters?
Populations always differ somehow. The question is whether they differ in a way that changes the effect. That is a claim about mechanisms, so it is answered on a graph — a **selection diagram**, in which every node whose mechanism differs between the two populations gets an extra parent S[node] standing for 'this one is not the same here'.
The verdict is not 'yes'. It is a formula, a named assumption, the set that licenses it, and the thing that would refute it. The source's age-specific effects reweighted by district B's age mix — which is why the strata weights on Population were not decoration.
from axiom.identify import CausalGraph, selection_diagram, transport_verdict
# What we believe about how illness comes about, and what differs
# between the districts: the age composition, and nothing else.
world = CausalGraph.from_edges(
"filters -> illness, age -> illness, age -> filters,"
" sanitation -> illness, sanitation -> filters",
selection=["age"],
name="two_districts",
)
print("the selection diagram makes the difference a node:")
for edge in sorted(selection_diagram(world).edges):
print(" ", " -> ".join(edge))
print()
verdict = transport_verdict(world, "filters", "illness")
print("status :", verdict.status)
print("route :", verdict.verdict.route)
print("set :", verdict.s_admissible_set)
print("formula :", verdict.formula)
print()
for a in verdict.verdict.assumptions:
print(f"assumption {a.name} [{a.state}]")
print(f" says {a.statement}")
print(f" refuted by {a.challenged_by}")
the selection diagram makes the difference a node:
S[age] -> age
age -> filters
age -> illness
filters -> illness
sanitation -> filters
sanitation -> illness
status : identified
route : s_admissible_adjustment
set : ('age',)
formula : P*(illness|do(filters)) = Σ_{age} P(illness|do(filters),age) P*(age)
assumption s_admissibility [satisfied]
says Z=['age'] is S-admissible for the effect of filters on illness: (illness ⊥ S | filters, Z) in G_bar(filters) of the selection diagram, so P*(illness|do(filters)) = Σ_{age} P(illness|do(filters),age) P*(age)
refuted by a mechanism difference between the populations the diagram omits
Every line above was captured by running this code at build time. The steps share one namespace, so the code on this page is the code you would type after the steps before it.