From 7e1c294b4ae138b84b20fc34917c39754eff1283 Mon Sep 17 00:00:00 2001 From: mschauer Date: Sun, 6 Aug 2023 17:39:16 +0200 Subject: [PATCH 1/3] Add Dor & Tasi --- docs/src/library.md | 1 + src/CausalInference.jl | 2 +- src/meek.jl | 5 +++-- src/pdag.jl | 37 +++++++++++++++++++++++++++++++++++++ test/cpdag.jl | 10 ++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/docs/src/library.md b/docs/src/library.md index 8e3f97a5..523d5f02 100644 --- a/docs/src/library.md +++ b/docs/src/library.md @@ -31,6 +31,7 @@ CausalInference.meek_rule2 CausalInference.meek_rule3 CausalInference.meek_rule4 pdag2dag! +pdag2dag_meek! ``` ## PC algorithm diff --git a/src/CausalInference.jl b/src/CausalInference.jl index 521f97a3..79250c86 100644 --- a/src/CausalInference.jl +++ b/src/CausalInference.jl @@ -25,7 +25,7 @@ export plot_pc_graph_recipes, plot_fci_graph_recipes # if GraphRecipes is loaded export plot_pc_graph_tikz, plot_fci_graph_tikz # if TikzGraphs is loaded export orient_unshielded, orientable_unshielded, apply_pc_rules export ges -export pdag2dag! +export pdag2dag!, pdag2dag_meek! #include("pinv.jl") include("graphs.jl") diff --git a/src/meek.jl b/src/meek.jl index 31a682a9..f2d2dca6 100644 --- a/src/meek.jl +++ b/src/meek.jl @@ -108,11 +108,11 @@ function meek_rule4(dg, v, w) end """ - pdag2dag!(g, rule4=false) + pdag2dag_meek!(g, rule4=false) Complete PDAG to DAG using meek_rules. """ -function pdag2dag!(g, rule4=false) +function pdag2dag_meek!(g, rule4=false) while true # find unoriented edge for e in edges(g) # go through edges (bad to start in the beginning?) @@ -127,4 +127,5 @@ function pdag2dag!(g, rule4=false) @label orient meek_rules!(g; rule4) end + g end diff --git a/src/pdag.jl b/src/pdag.jl index eeb39f3d..9e23ef93 100644 --- a/src/pdag.jl +++ b/src/pdag.jl @@ -147,3 +147,40 @@ Children of x in g are vertices y such that there is a directed edge y <-- x. Returns sorted array. """ children(g, x) = setdiff(outneighbors(g, x), inneighbors(g, x)) + +""" + pdag2dag!(g, rule4=false) + +Complete PDAG to DAG using Dor & Tasi (1992). +""" +function pdag2dag!(g) + removed = falses(nv(g)) # Mark vertices removed from (sub-)graph A. Efficient if degree small? + while !all(removed) + touched = false + for x in vertices(g) + removed[x] && continue + for y in outneighbors(g, x) + removed[y] && continue + has_edge(g, y, x) || @goto skip # not a sink + end + for y in neighbors_undirected(g, x) + removed[y] && continue + for z in inneighbors(g, x) # contains all adjacents by assumption + removed[z] && continue + y==z || isadjacent(g, y, z) || @goto skip + end + end + for y in copy(outneighbors(g, x)) + removed[y] && continue + rem_edge!(g, x, y) + end + touched = true + removed[x] = true + @label skip + end + if !touched + error("PDAG has no consistent extension to a DAG") + end + end + return g +end diff --git a/test/cpdag.jl b/test/cpdag.jl index 021ec394..b8524e38 100644 --- a/test/cpdag.jl +++ b/test/cpdag.jl @@ -57,6 +57,16 @@ for stable in (true, false) h1 = pc_oracle(g; stable) h2 = cpdag(g) + + g2 = pdag2dag!(copy(h2)) + @test !is_cyclic(g2) + @test h2 == cpdag(g2) + + g2 = pdag2dag_meek!(copy(h2)) + @test !is_cyclic(g2) + @test h2 == cpdag(g2) + + h1 == h2 || println(vpairs(g)) @test vpairs(h1) ⊆ vpairs(h2) @test vpairs(h2) ⊆ vpairs(h1) From 4543cdbe1bc860801bb4e971c215d0dbcc96fe1d Mon Sep 17 00:00:00 2001 From: Moritz Schauer Date: Sun, 6 Aug 2023 18:19:27 +0200 Subject: [PATCH 2/3] Update src/pdag.jl --- src/pdag.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pdag.jl b/src/pdag.jl index 9e23ef93..33bba0f6 100644 --- a/src/pdag.jl +++ b/src/pdag.jl @@ -149,7 +149,7 @@ Returns sorted array. children(g, x) = setdiff(outneighbors(g, x), inneighbors(g, x)) """ - pdag2dag!(g, rule4=false) + pdag2dag!(g) Complete PDAG to DAG using Dor & Tasi (1992). """ From b8f0bcb590148b45f11260ca07a4d3b0c78df168 Mon Sep 17 00:00:00 2001 From: mschauer Date: Mon, 7 Aug 2023 10:58:41 +0200 Subject: [PATCH 3/3] Make it non-breaking --- docs/src/library.md | 3 ++- src/CausalInference.jl | 2 +- src/meek.jl | 8 ++++++-- src/pdag.jl | 4 ++-- test/cpdag.jl | 4 ++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/src/library.md b/docs/src/library.md index 523d5f02..3d489394 100644 --- a/docs/src/library.md +++ b/docs/src/library.md @@ -31,7 +31,8 @@ CausalInference.meek_rule2 CausalInference.meek_rule3 CausalInference.meek_rule4 pdag2dag! -pdag2dag_meek! +pdag_to_dag_dortasi! +pdag_to_dag_meek! ``` ## PC algorithm diff --git a/src/CausalInference.jl b/src/CausalInference.jl index 79250c86..1d4b70ea 100644 --- a/src/CausalInference.jl +++ b/src/CausalInference.jl @@ -25,7 +25,7 @@ export plot_pc_graph_recipes, plot_fci_graph_recipes # if GraphRecipes is loaded export plot_pc_graph_tikz, plot_fci_graph_tikz # if TikzGraphs is loaded export orient_unshielded, orientable_unshielded, apply_pc_rules export ges -export pdag2dag!, pdag2dag_meek! +export pdag2dag!, pdag_to_dag_meek!, pdag_to_dag_dortasi! #include("pinv.jl") include("graphs.jl") diff --git a/src/meek.jl b/src/meek.jl index f2d2dca6..955e1b40 100644 --- a/src/meek.jl +++ b/src/meek.jl @@ -108,11 +108,11 @@ function meek_rule4(dg, v, w) end """ - pdag2dag_meek!(g, rule4=false) + pdag_to_dag_meek!(g, rule4=false) Complete PDAG to DAG using meek_rules. """ -function pdag2dag_meek!(g, rule4=false) +function pdag_to_dag_meek!(g, rule4=false) while true # find unoriented edge for e in edges(g) # go through edges (bad to start in the beginning?) @@ -129,3 +129,7 @@ function pdag2dag_meek!(g, rule4=false) end g end +""" +Deprecated alias for `pdag_to_dag_meek!`. +""" +const pdag2dag! = pdag_to_dag_meek! \ No newline at end of file diff --git a/src/pdag.jl b/src/pdag.jl index 33bba0f6..9051e61d 100644 --- a/src/pdag.jl +++ b/src/pdag.jl @@ -149,11 +149,11 @@ Returns sorted array. children(g, x) = setdiff(outneighbors(g, x), inneighbors(g, x)) """ - pdag2dag!(g) + pdag_to_dag_dortasi!!(g) Complete PDAG to DAG using Dor & Tasi (1992). """ -function pdag2dag!(g) +function pdag_to_dag_dortasi!(g) removed = falses(nv(g)) # Mark vertices removed from (sub-)graph A. Efficient if degree small? while !all(removed) touched = false diff --git a/test/cpdag.jl b/test/cpdag.jl index b8524e38..bdad8dbe 100644 --- a/test/cpdag.jl +++ b/test/cpdag.jl @@ -58,11 +58,11 @@ for stable in (true, false) h1 = pc_oracle(g; stable) h2 = cpdag(g) - g2 = pdag2dag!(copy(h2)) + g2 = pdag_to_dag_dortasi!(copy(h2)) @test !is_cyclic(g2) @test h2 == cpdag(g2) - g2 = pdag2dag_meek!(copy(h2)) + g2 = pdag_to_dag_meek!(copy(h2)) @test !is_cyclic(g2) @test h2 == cpdag(g2)