@@ -8,22 +8,19 @@ Check whether `u` and `v` are d-separated given set `s`.
8
8
Algorithm: unrolled https://arxiv.org/abs/1304.1505
9
9
10
10
"""
11
- function dsep (g:: AbstractGraph , u :: Integer , v :: Integer , S; verbose = false )
11
+ function dsep (g:: AbstractGraph , U, V , S; verbose = false )
12
12
T = eltype (g)
13
13
in_seen = falses (nv (g)) # nodes reached earlier backwards
14
14
out_seen = falses (nv (g)) # nodes reached earlier forwards
15
15
descendant = falses (nv (g)) # descendant in s
16
+ isv = falses (nv (g))
16
17
blocked = falses (nv (g))
17
18
18
19
for ve in S
19
20
in_seen[ve] = true
20
21
blocked[ve] = true
21
22
end
22
23
23
- (in_seen[u] || in_seen[v]) && throw (ArgumentError (" S should not contain u or v" ))
24
-
25
- u == v && throw (ArgumentError (" u == v" ))
26
-
27
24
next = Vector {T} ()
28
25
29
26
# mark vertices with descendants in S
@@ -47,9 +44,25 @@ function dsep(g::AbstractGraph, u::Integer, v::Integer, S; verbose = false)
47
44
in_next = Vector {T} ()
48
45
out_next = Vector {T} ()
49
46
50
- push! (in_next, u) # treat u as vertex reached backwards
51
- in_seen[u] = true
47
+ for u in U
48
+ push! (in_next, u) # treat u as vertex reached backwards
49
+ in_seen[u] && throw (ArgumentError (" U and S not disjoint." ))
50
+ in_seen[u] = true
51
+ end
52
+ if V isa Integer
53
+ in_seen[V] && throw (ArgumentError (" U, V and S not disjoint." ))
54
+ return dsep_inner! (g, in_next, out_next, descendant, == (V), blocked, out_seen, in_seen; verbose)
55
+ else
56
+ isv = falses (nv (g))
57
+ for v in V
58
+ in_seen[v] && throw (ArgumentError (" U, V and S not disjoint." ))
59
+ isv[v] = true
60
+ end
61
+ return dsep_inner! (g, in_next, out_next, descendant, w-> isv[w], blocked, out_seen, in_seen; verbose)
62
+ end
63
+ end
52
64
65
+ function dsep_inner! (g, in_next, out_next, descendant, found, blocked, out_seen, in_seen; verbose= false )
53
66
while true
54
67
sin = isempty (in_next)
55
68
sout = isempty (out_next)
@@ -60,15 +73,15 @@ function dsep(g::AbstractGraph, u::Integer, v::Integer, S; verbose = false)
60
73
for w in outneighbors (g, src) # possible collider at destination
61
74
if ! out_seen[w] && (! blocked[w] || descendant[w])
62
75
verbose && println (" <- $src -> $w " )
63
- w == v && return false
76
+ found (w) && return false
64
77
push! (out_next, w)
65
78
out_seen[w] = true
66
79
end
67
80
end
68
81
for w in inneighbors (g, src)
69
82
if ! in_seen[w]
70
83
verbose && println (" <- $src <- $w " )
71
- w == v && return false
84
+ found (w) && return false
72
85
push! (in_next, w)
73
86
in_seen[w] = true
74
87
end
@@ -79,15 +92,15 @@ function dsep(g::AbstractGraph, u::Integer, v::Integer, S; verbose = false)
79
92
for w in outneighbors (g, src) # possible collider at destination
80
93
if ! out_seen[w] && ! blocked[src] && (! blocked[w] || descendant[w])
81
94
verbose && println (" -> $src -> $w " )
82
- w == v && return false
95
+ found (w) && return false
83
96
push! (out_next, w)
84
97
out_seen[w] = true
85
98
end
86
99
end
87
100
for w in inneighbors (g, src) # collider at source
88
101
if ! in_seen[w] && descendant[src] # shielded collider
89
102
verbose && println (" -> $src <- $w " )
90
- w == v && return false
103
+ found (w) && return false
91
104
push! (out_next, w)
92
105
in_seen[w] = true
93
106
end
0 commit comments