Skip to content

Commit 0257ff5

Browse files
committed
Rel 0.1.0
1 parent 39572e1 commit 0257ff5

File tree

8 files changed

+699
-3
lines changed

8 files changed

+699
-3
lines changed

notebooks/confounding_triangles.ipynb

Lines changed: 346 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"metadata": {},
7+
"outputs": [
8+
{
9+
"name": "stderr",
10+
"output_type": "stream",
11+
"text": [
12+
"┌ Info: Precompiling StructuralCausalModels [a41e6734-49ce-4065-8b83-aff084c01dfd]\n",
13+
"└ @ Base loading.jl:1278\n"
14+
]
15+
}
16+
],
17+
"source": [
18+
"using StructuralCausalModels, Test"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": 2,
24+
"metadata": {},
25+
"outputs": [],
26+
"source": [
27+
"ProjDir = scm_path(\"..\")\n",
28+
"cd(ProjDir) #do"
29+
]
30+
},
31+
{
32+
"cell_type": "code",
33+
"execution_count": 3,
34+
"metadata": {},
35+
"outputs": [
36+
{
37+
"data": {
38+
"text/plain": [
39+
"\"/Users/rob/.julia/dev/StructuralCausalModels/\""
40+
]
41+
},
42+
"execution_count": 3,
43+
"metadata": {},
44+
"output_type": "execute_result"
45+
}
46+
],
47+
"source": [
48+
"ProjDir"
49+
]
50+
},
51+
{
52+
"cell_type": "code",
53+
"execution_count": 4,
54+
"metadata": {},
55+
"outputs": [],
56+
"source": [
57+
"fname = scm_path(\"..\", \"examples\", \"Shipley\", \"fig2.6\", \"fig2.6.dot\")\n",
58+
"Sys.isapple() && run(`open -a GraphViz.app $(fname)`);"
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": 5,
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"# Read `=>` as `~` in regression models, or `<-` in causal models.\n",
68+
"d = OrderedDict(\n",
69+
" :u => [:x, :v],\n",
70+
" :s1 => [:u],\n",
71+
" :w => [:v, :y],\n",
72+
" :s2 => [:w]\n",
73+
");"
74+
]
75+
},
76+
{
77+
"cell_type": "code",
78+
"execution_count": 6,
79+
"metadata": {},
80+
"outputs": [],
81+
"source": [
82+
"dag = DAG(\"fig2.6\", d);"
83+
]
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": 7,
88+
"metadata": {},
89+
"outputs": [
90+
{
91+
"data": {
92+
"text/plain": [
93+
"7×7 Named Array{Int64,2}\n",
94+
"Cols ╲ Rows │ :u :x :v :s1 :w :y :s2\n",
95+
"────────────┼──────────────────────────────────\n",
96+
":u │ 0 1 1 0 0 0 0\n",
97+
":x │ 0 0 0 0 0 0 0\n",
98+
":v │ 0 0 0 0 0 0 0\n",
99+
":s1 │ 1 0 0 0 0 0 0\n",
100+
":w │ 0 0 1 0 0 1 0\n",
101+
":y │ 0 0 0 0 0 0 0\n",
102+
":s2 │ 0 0 0 0 1 0 0"
103+
]
104+
},
105+
"execution_count": 7,
106+
"metadata": {},
107+
"output_type": "execute_result"
108+
}
109+
],
110+
"source": [
111+
"dag.a"
112+
]
113+
},
114+
{
115+
"cell_type": "code",
116+
"execution_count": 8,
117+
"metadata": {},
118+
"outputs": [
119+
{
120+
"data": {
121+
"text/plain": [
122+
"true"
123+
]
124+
},
125+
"execution_count": 8,
126+
"metadata": {},
127+
"output_type": "execute_result"
128+
}
129+
],
130+
"source": [
131+
"to_ggm(dag) == \"DAG(u ~ x + v, s1 ~ u, w ~ v + y, s2 ~ w)\""
132+
]
133+
},
134+
{
135+
"cell_type": "code",
136+
"execution_count": 9,
137+
"metadata": {},
138+
"outputs": [
139+
{
140+
"data": {
141+
"text/plain": [
142+
"true"
143+
]
144+
},
145+
"execution_count": 9,
146+
"metadata": {},
147+
"output_type": "execute_result"
148+
}
149+
],
150+
"source": [
151+
"d_separation(dag, :x, :v)"
152+
]
153+
},
154+
{
155+
"cell_type": "code",
156+
"execution_count": 15,
157+
"metadata": {},
158+
"outputs": [
159+
{
160+
"data": {
161+
"text/plain": [
162+
"true"
163+
]
164+
},
165+
"execution_count": 15,
166+
"metadata": {},
167+
"output_type": "execute_result"
168+
}
169+
],
170+
"source": [
171+
"m_separation(dag, :x, :v)"
172+
]
173+
},
174+
{
175+
"cell_type": "code",
176+
"execution_count": 14,
177+
"metadata": {},
178+
"outputs": [
179+
{
180+
"name": "stdout",
181+
"output_type": "stream",
182+
"text": [
183+
"\u001b[37m\u001b[1mTest Summary: | \u001b[22m\u001b[39m\u001b[32m\u001b[1mPass \u001b[22m\u001b[39m\u001b[36m\u001b[1mTotal\u001b[22m\u001b[39m\n",
184+
"m_separation_02 | \u001b[32m 12 \u001b[39m\u001b[36m 12\u001b[39m\n"
185+
]
186+
}
187+
],
188+
"source": [
189+
"@testset \"m_separation_02\" begin\n",
190+
" \n",
191+
" @test to_ggm(dag) == \"DAG(u ~ x + v, s1 ~ u, w ~ v + y, s2 ~ w)\"\n",
192+
" @test m_separation(dag, :x, :v; debug=false) == true\n",
193+
" @test m_separation(dag, :x, [:v]; c=:u, debug=false) == false\n",
194+
" @test m_separation(dag, [:x], :v; c=:s1, debug=false) == false\n",
195+
" @test m_separation(dag, [:u], [:w]; debug=false) == false\n",
196+
" @test m_separation(dag, :u, [:w]; c=:v, debug=false) == true\n",
197+
"\n",
198+
" @test m_separation(dag, [:x], :y) == true\n",
199+
" @test m_separation(dag, :x, :y; c=[:u, :w], debug=false) == false\n",
200+
" @test m_separation(dag, :x, :y; c=[:s1, :s2], debug=false) == false\n",
201+
" @test m_separation(dag, :x, :y; c=[:u, :v, :w], debug=false) == true\n",
202+
" @test m_separation(dag, :x, [:v]; c=:u, debug=false) == false\n",
203+
" @test m_separation(dag, [:x], :v; c=:s1, debug=false) == false;\n",
204+
"\n",
205+
"end;"
206+
]
207+
},
208+
{
209+
"cell_type": "code",
210+
"execution_count": null,
211+
"metadata": {},
212+
"outputs": [],
213+
"source": []
214+
}
215+
],
216+
"metadata": {
217+
"@webio": {
218+
"lastCommId": null,
219+
"lastKernelId": null
220+
},
221+
"kernelspec": {
222+
"display_name": "Julia 1.5",
223+
"language": "julia",
224+
"name": "julia-1.5"
225+
},
226+
"language_info": {
227+
"file_extension": ".jl",
228+
"mimetype": "application/julia",
229+
"name": "julia",
230+
"version": "1.5.0"
231+
}
232+
},
233+
"nbformat": 4,
234+
"nbformat_minor": 2
235+
}

research/graph_recipes/ex01.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
using StructuralCausalModels
22
using GraphRecipes, Plots
33

4-
include("/Users/rob/.julia/dev/StructuralCausalModels/examples/dagitty/confounding_triangle.jl");
4+
ProjDir = @__DIR__
5+
cd(ProjDir) #do
56

6-
graphplot(dag.e, names=names(dag.e, 1), curvature_scalar=0.1, nodesize=0.5,
7-
method=:spring, fontsize=10, arrow=1.0)
7+
d_string = "dag {A -> {E Z}; B -> {D Z}; Z -> {D E}; E -> D}"
8+
9+
dag = DAG("conf_triangles", d_string);
10+
show(dag)
11+
12+
graphplot(dag.e, names=names(dag.e, 1), curvature_scalar=0.1, nodesize=0.2,
13+
method=:spring, fontsize=10, arrow=1.0, nodeshape=:circle)
814

915
gui()

src/methods/induced_covariance_graph.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ function induced_covariance_graph(d::DAG, sel, c; debug=false)
6868
elseif length(c) > 0
6969
cs = c
7070
end
71+
7172
@assert all([c in d.vars for c in cs]) "Conditioning nodes are not among vertices."
7273
#@assert !(length([cs in sel]) > 0) "Conditioning nodes in selected nodes."
7374

src/methods/m_separation.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ Part of the API, exported.
6363
function m_separation(d::DAG, f::SymbolList, s::SymbolList;
6464
c::SymbolListOrNothing=nothing, debug=false)
6565

66+
if typeof(f) == Symbol
67+
f = [f]
68+
end
69+
if typeof(s) == Symbol
70+
s = [s]
71+
end
72+
if typeof(c) == Symbol
73+
c = [c]
74+
end
75+
6676
if isnothing(c)
6777
m = setdiff(d.vars, vcat(f, s))
6878
debug && println("m = $m")

test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ include("test_ribbon_graph.jl")
2727
include("test_maximize.jl")
2828
#include("test_maximize_02.jl")
2929
include("test_m_separation.jl")
30+
include("test_m_separation_02.jl")
31+
include("test_m_separation_03.jl")
3032

3133
include("test_sr6_4_2.jl")
3234

test/test_m_separation_02.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using StructuralCausalModels, Test
2+
3+
ProjDir = @__DIR__
4+
cd(ProjDir) #do
5+
6+
fname = scm_path("..", "examples", "Shipley", "fig2.6", "fig2.6.dot")
7+
#Sys.isapple() && run(`open -a GraphViz.app $(fname)`)
8+
9+
# Read `=>` as `~` in regression models, or `<-` in causal models.
10+
d = OrderedDict(
11+
:u => [:x, :v],
12+
:s1 => [:u],
13+
:w => [:v, :y],
14+
:s2 => [:w]
15+
);
16+
17+
dag = DAG("fig2.6", d);
18+
19+
@testset "m_separation_02" begin
20+
21+
@test to_ggm(dag) == "DAG(u ~ x + v, s1 ~ u, w ~ v + y, s2 ~ w)"
22+
@test m_separation(dag, :x, :v; debug=false) == true
23+
@test m_separation(dag, :x, [:v]; c=:u, debug=false) == false
24+
@test m_separation(dag, [:x], :v; c=:s1, debug=false) == false
25+
@test m_separation(dag, [:u], [:w]; debug=false) == false
26+
@test m_separation(dag, :u, [:w]; c=:v, debug=false) == true
27+
28+
@test m_separation(dag, [:x], :y) == true
29+
@test m_separation(dag, :x, :y; c=[:u, :w], debug=false) == false
30+
@test m_separation(dag, :x, :y; c=[:s1, :s2], debug=false) == false
31+
@test m_separation(dag, :x, :y; c=[:u, :v, :w], debug=false) == true
32+
@test m_separation(dag, :x, [:v]; c=:u, debug=false) == false
33+
@test m_separation(dag, [:x], :v; c=:s1, debug=false) == false
34+
35+
end

test/test_m_separation_03.jl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using StructuralCausalModels, Test
2+
3+
ProjDir = @__DIR__
4+
cd(ProjDir) #do
5+
6+
ProjDir = @__DIR__
7+
8+
d_str = "dag{k1 -> k2;k2 -> y;v -> x2;w -> k1;x1 -> v;x1 -> w;x2 -> y;x3 -> w;x3 -> y}"
9+
10+
dag = DAG("test_desc_02", d_str)
11+
12+
@testset "m_separation_03" begin
13+
14+
@test m_separation(dag, :k1, :v, c=[:x1]) == true
15+
@test m_separation(dag, :k1, :v, c=[:w]) == true
16+
@test m_separation(dag, :k1, :x1, c=[:w]) == true
17+
@test m_separation(dag, :k1, :x2, c=[:v]) == true
18+
@test m_separation(dag, :k1, :x2, c=[:x1]) == true
19+
@test m_separation(dag, :k1, :x2, c=[:w]) == true
20+
@test m_separation(dag, :k1, :x3, c=[:w]) == true
21+
@test m_separation(dag, :k1, :y, c=[:k2, :x2, :x3]) == true
22+
@test m_separation(dag, :k1, :y, c=[:k2, :v, :x3]) == true
23+
@test m_separation(dag, :k1, :y, c=[:k2, :x1, :x3]) == true
24+
@test m_separation(dag, :k1, :y, c=[:k2, :w]) == true
25+
@test m_separation(dag, :k2, :v, c=[:x1]) == true
26+
@test m_separation(dag, :k2, :v, c=[:w]) == true
27+
@test m_separation(dag, :k2, :v, c=[:k1]) == true
28+
@test m_separation(dag, :k2, :w, c=[:k1]) == true
29+
@test m_separation(dag, :k2, :x1, c=[:w]) == true
30+
@test m_separation(dag, :k2, :x1, c=[:k1]) == true
31+
@test m_separation(dag, :k2, :x2, c=[:v]) == true
32+
@test m_separation(dag, :k2, :x2, c=[:x1]) == true
33+
@test m_separation(dag, :k2, :x2, c=[:w]) == true
34+
@test m_separation(dag, :k2, :x2, c=[:k1]) == true
35+
@test m_separation(dag, :k2, :x3, c=[:w]) == true
36+
@test m_separation(dag, :k2, :x3, c=[:k1]) == true
37+
@test m_separation(dag, :v, :w; c=:x1) == true
38+
@test m_separation(dag, :v, :x3) == true
39+
@test m_separation(dag, :v, :y; c=[:k2, :x2, :x3]) == true
40+
@test m_separation(dag, :v, :y; c=[:k1, :x2, :x3]) == true
41+
@test m_separation(dag, :v, :y; c=[:w, :x2, :x3]) == true
42+
@test m_separation(dag, :v, :y; c=[:x2, :x1]) == true
43+
@test m_separation(dag, :w, :x2; c=[:v]) == true
44+
@test m_separation(dag, :w, :x2; c=[:x1]) == true
45+
@test m_separation(dag, :w, :y; c=[:k2, :x2, :x3]) == true
46+
@test m_separation(dag, :w, :y; c=[:k2, :v, :x3]) == true
47+
@test m_separation(dag, :w, :y; c=[:k1, :x2, :x3]) == true
48+
@test m_separation(dag, :w, :y; c=[:k1, :v, :x3]) == true
49+
@test m_separation(dag, :w, :y; c=[:k1, :x1, :x3]) == true
50+
@test m_separation(dag, :w, :y; c=[:k2, :x2, :x3]) == true
51+
@test m_separation(dag, :x1, :x2; c=[:v]) == true
52+
@test m_separation(dag, :x1, :x3) == true
53+
@test m_separation(dag, :x1, :y; c=[:k2, :x2, :x3]) == true
54+
@test m_separation(dag, :x1, :y; c=[:k1, :x2, :x3]) == true
55+
@test m_separation(dag, :x1, :y; c=[:w, :x2, :x3]) == true
56+
@test m_separation(dag, :x1, :y; c=[:k2, :v, :x3]) == true
57+
@test m_separation(dag, :x1, :y; c=[:k1, :v, :x3]) == true
58+
@test m_separation(dag, :x1, :y; c=[:v, :w, :x3]) == true
59+
@test m_separation(dag, :x2, :x3) == true
60+
61+
end

0 commit comments

Comments
 (0)