Meek's approach we currently use in PC and GES is: Take the PDAG and apply R1-R4 repeatedly until no rule applies. To obtain the CPDAG from a pattern the rules R1-R3 suffice, R4 is not needed.
Chickering's approach is to take the PDAG and find a DAG with same skeleton and v-structures. (This can be done e.g. with this algorithm by Dor and Tarsi: https://ftp.cs.ucla.edu/pub/stat_ser/r185-dor-tarsi.pdf) From the DAG construct the CPDAG (which is possible in linear-time, we also have this implemented cpdag(g)).
Implementing Chickerings approach would be an option because the complicated part (from an implementation perspective) is DAG-to-CPDAG which we already have. A straightforward implementation of PDAG to DAG by Dor and Tarsi are just a few lines. For speed of PC and GES this will likely not matter too much overall, other parts are more costly in case of PC the pattern learned from data might not have a DAG with same skeleton and v-structures. Then, it is not clear how to use Chickerings approach.
R4 is only needed in case of background knowledge, i.e. some edge orientations which do not follow from v-structures. For soundness of the rule, it is necessary that v and l are adjacent. For completeness of the Meek rules it suffices to apply it only if there is an undirected edge.
Settings
This document was generated with Documenter.jl on Saturday 7 December 2024. Using Julia version 1.11.2.
Meek's approach we currently use in PC and GES is: Take the PDAG and apply R1-R4 repeatedly until no rule applies. To obtain the CPDAG from a pattern the rules R1-R3 suffice, R4 is not needed.
Chickering's approach is to take the PDAG and find a DAG with same skeleton and v-structures. (This can be done e.g. with this algorithm by Dor and Tarsi: https://ftp.cs.ucla.edu/pub/stat_ser/r185-dor-tarsi.pdf) From the DAG construct the CPDAG (which is possible in linear-time, we also have this implemented cpdag(g)).
Implementing Chickerings approach would be an option because the complicated part (from an implementation perspective) is DAG-to-CPDAG which we already have. A straightforward implementation of PDAG to DAG by Dor and Tarsi are just a few lines. For speed of PC and GES this will likely not matter too much overall, other parts are more costly in case of PC the pattern learned from data might not have a DAG with same skeleton and v-structures. Then, it is not clear how to use Chickerings approach.
R4 is only needed in case of background knowledge, i.e. some edge orientations which do not follow from v-structures. For soundness of the rule, it is necessary that v and l are adjacent. For completeness of the Meek rules it suffices to apply it only if there is an undirected edge.
Settings
This document was generated with Documenter.jl on Saturday 7 December 2024. Using Julia version 1.11.2.
diff --git a/dev/examples/backdoor_example/index.html b/dev/examples/backdoor_example/index.html
index aa2b8665..81051742 100644
--- a/dev/examples/backdoor_example/index.html
+++ b/dev/examples/backdoor_example/index.html
@@ -20,4 +20,4 @@
t = plot_pc_graph_tikz(dag)
We are interested in the average causal effect (ACE) of a treatment X (variable nr. 6) on an outcome Y (variable nr. 8), which stands for the expected increase of Y per unit of a controlled increase in X. Variables nr. 1 and nr. 2 are unobserved.
Regressing Y (nr. 8) on X (nr. 6) will fail to measure the effect because of the presence of a confounder C (variable nr. 4), which opens a backdoor path, a connection between X and Y via the path 6 ← 4 → 8 which is not causal.
We can avert such problems by checking the backdoor criterion. Indeed
backdoor_criterion(dag, 6, 8) # false
reports a problem.
One might want to condition on the confounder C (nr. 4)` to obtain the causal effect, but then
backdoor_criterion(dag, 6, 8, [4]) # still false
there is still a problem ( because that conditioning opens up a non-causal path via 6 ← 3 ← 1 → 4 ← 2 → 5 → 8.)
But conditioning on both Z = [4, 5] solves the problem, as verified by the backdoor criterion.
(also conditioning on Z = [3, 4] would be possible.)
Thus, regressing Y on X and controlling for variables numbered Z = [4, 5] we measure the average causal effect.
What we have done by hand here is the search for an backdoor adjustment set. We could have directly queried
Zs = list_covariate_adjustment(dag, 6, 8, Int[], setdiff(Set(1:8), [1, 2])) # exclude variables nr. 1 and nr. 2 because they are unobserved.
which lists possible adjustment sets,
println.(Zs);
Set([4, 3])
Set([5, 4])
- Set([5, 4, 3])
to get the list of possible adjustment sets. Here list_backdoor_adjustment gives adjustment sets for a backdoor criterion similar to backdoor_criterion and list_covariate_adjustment the more versatile adjustment set based on the sound and complete graphical criterion for covariate adjustment given in [https://arxiv.org/abs/1203.3515] using the algorithmic approach proposed in [https://arxiv.org/abs/1803.00116].
Settings
This document was generated with Documenter.jl on Saturday 7 December 2024. Using Julia version 1.11.2.