From f9b26ce69da8fb96b75abb46f5c581a95c082dcc Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Sun, 3 Mar 2024 10:12:50 +0530 Subject: [PATCH 1/9] Added files for complete adjustment criterion Signed-off-by: Aryan Roy --- dowhy/causal_identifier/complete_adjustment.py | 1 + tests/causal_identifiers/test_complete_adjustment.py | 1 + 2 files changed, 2 insertions(+) create mode 100644 dowhy/causal_identifier/complete_adjustment.py create mode 100644 tests/causal_identifiers/test_complete_adjustment.py diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py new file mode 100644 index 0000000000..887a3d40fa --- /dev/null +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -0,0 +1 @@ +import networkx as nx \ No newline at end of file diff --git a/tests/causal_identifiers/test_complete_adjustment.py b/tests/causal_identifiers/test_complete_adjustment.py new file mode 100644 index 0000000000..bb377e8991 --- /dev/null +++ b/tests/causal_identifiers/test_complete_adjustment.py @@ -0,0 +1 @@ +import pytest \ No newline at end of file From c4633d583ef4a561668773a0715aba2c5bc092fd Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Mon, 4 Mar 2024 18:10:39 +0530 Subject: [PATCH 2/9] Added some unit tests for adjustable vs not Signed-off-by: Aryan Roy --- .../causal_identifier/complete_adjustment.py | 8 ++- .../test_complete_adjustment.py | 55 ++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index 887a3d40fa..891782ce68 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -1 +1,7 @@ -import networkx as nx \ No newline at end of file +import networkx as nx + +import pywhy_graphs + +class CompleteAdjustment: + def adjustable(G): + pass \ No newline at end of file diff --git a/tests/causal_identifiers/test_complete_adjustment.py b/tests/causal_identifiers/test_complete_adjustment.py index bb377e8991..7166cd16e7 100644 --- a/tests/causal_identifiers/test_complete_adjustment.py +++ b/tests/causal_identifiers/test_complete_adjustment.py @@ -1 +1,54 @@ -import pytest \ No newline at end of file +import pytest + +from pywhy_graphs import MAG, PAG + +from dowhy.causal_identifier.complete_adjustment import CompleteAdjustment + +def test_complete_adjsutment(): + G = MAG() + G.add_edge("Z", "X", G.directed_edge_name) + G.add_edge("Z", "Y", G.directed_edge_name) + G.add_edge("X", "Y", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G) + + G = MAG() + G.add_edge("X", "Z", G.directed_edge_name) + G.add_edge("X", "Y", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G) + + G = MAG() + G.add_edge("X", "Z", G.directed_edge_name) + G.add_edge("Z", "Y", G.directed_edge_name) + G.add_edge("U", "X", G.directed_edge_name) + G.add_edge("U", "Y", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert not cad.adjustable(G) + + G = PAG() + G.add_edge("I", "X", G.directed_edge_name) + G.add_edge("Z", "X", G.directed_edge_name) + G.add_edge("A", "X", G.directed_edge_name) + G.add_edge("X", "Y", G.directed_edge_name) + G.add_edge("Z", "Y", G.directed_edge_name) + G.add_edge("B", "Y", G.directed_edge_name) + G.add_edge("B", "Z", G.circle_edge_name) + G.add_edge("Z", "B", G.circle_edge_name) + G.add_edge("A", "B", G.circle_edge_name) + G.add_edge("B", "A", G.circle_edge_name) + G.add_edge("A", "Z", G.circle_edge_name) + G.add_edge("Z", "A", G.circle_edge_name) + G.add_edge("A", "I", G.circle_edge_name) + G.add_edge("I", "A", G.circle_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G) + From dd140582c6ae9eb700e1ee799ce60bb1c947bd3d Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Wed, 6 Mar 2024 19:10:39 +0530 Subject: [PATCH 3/9] Added some more unit tests Signed-off-by: Aryan Roy --- .../test_complete_adjustment.py | 88 ++++++++++++++++++- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/tests/causal_identifiers/test_complete_adjustment.py b/tests/causal_identifiers/test_complete_adjustment.py index 7166cd16e7..008fb58d64 100644 --- a/tests/causal_identifiers/test_complete_adjustment.py +++ b/tests/causal_identifiers/test_complete_adjustment.py @@ -5,6 +5,7 @@ from dowhy.causal_identifier.complete_adjustment import CompleteAdjustment def test_complete_adjsutment(): + G = MAG() G.add_edge("Z", "X", G.directed_edge_name) G.add_edge("Z", "Y", G.directed_edge_name) @@ -12,7 +13,8 @@ def test_complete_adjsutment(): cad = CompleteAdjustment() - assert cad.adjustable(G) + assert cad.adjustable(G, {"X"}, {"Y"}) + G = MAG() G.add_edge("X", "Z", G.directed_edge_name) @@ -20,7 +22,8 @@ def test_complete_adjsutment(): cad = CompleteAdjustment() - assert cad.adjustable(G) + assert cad.adjustable(G, {"X"}, {"Y"}) + G = MAG() G.add_edge("X", "Z", G.directed_edge_name) @@ -30,7 +33,8 @@ def test_complete_adjsutment(): cad = CompleteAdjustment() - assert not cad.adjustable(G) + assert not cad.adjustable(G, {"X"}, {"Y"}) + G = PAG() G.add_edge("I", "X", G.directed_edge_name) @@ -50,5 +54,81 @@ def test_complete_adjsutment(): cad = CompleteAdjustment() - assert cad.adjustable(G) + assert cad.adjustable(G, {"X"},{"Y"}) + + G = MAG() + G.add_edge("A", "B", G.directed_edge_name) + G.add_edge("B", "C", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("D", "E", G.directed_edge_name) + G.add_edge("A", "E", G.directed_edge_name) + G.add_edge("F", "C", G.directed_edge_name) + G.add_edge("F", "E", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G, {"A", "D"}, {"E","F"}) + + G = MAG() + G.add_edge("A", "B", G.directed_edge_name) + G.add_edge("B", "C", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("D", "E", G.directed_edge_name) + G.add_edge("A", "E", G.directed_edge_name) + G.add_edge("F", "C", G.directed_edge_name) + G.add_edge("F", "E", G.directed_edge_name) + G.add_edge("A", "F", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert not cad.adjustable(G, {"A", "D"}, {"E","F"} ) + + + G = MAG() + G.add_edge("A", "B", G.directed_edge_name) + G.add_edge("B", "C", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("D", "E", G.directed_edge_name) + G.add_edge("A", "F", G.directed_edge_name) + G.add_edge("F", "E", G.directed_edge_name) + G.add_edge("G", "F", G.directed_edge_name) + G.add_edge("G", "C", G.directed_edge_name) + G.add_edge("H", "A", G.directed_edge_name) + G.add_edge("I", "A", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G, {"A", "D"}, {"E"} ) + + G = PAG() + G.add_edge("A", "B", G.directed_edge_name) + G.add_edge("B", "C", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("D", "E", G.directed_edge_name) + G.add_edge("A", "F", G.directed_edge_name) + G.add_edge("F", "E", G.directed_edge_name) + G.add_edge("F", "C", G.bidirected_edge_name) + G.add_edge("H", "A", G.directed_edge_name) + G.add_edge("I", "A", G.directed_edge_name) + G.add_edge("A", "H", G.circle_edge_name) + G.add_edge("A", "I", G.circle_edge_name) + + cad = CompleteAdjustment() + + assert cad.adjustable(G, {"A", "D"}, {"E"} ) + + G = MAG() + G.add_edge("B", "A", G.directed_edge_name) + G.add_edge("C", "B", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("E", "D", G.directed_edge_name) + G.add_edge("E", "F", G.directed_edge_name) + G.add_edge("F", "A", G.directed_edge_name) + G.add_edge("A", "D", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert not cad.adjustable(G, {"A", "C"}, {"D"} ) + + From 9dc346a90a7d5a0cd19287da32b454e4d71c2bdb Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Tue, 9 Apr 2024 17:59:24 +0530 Subject: [PATCH 4/9] Segmented the tests based on graph type Signed-off-by: Aryan Roy --- .../test_complete_adjustment.py | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/causal_identifiers/test_complete_adjustment.py b/tests/causal_identifiers/test_complete_adjustment.py index 008fb58d64..fd4533d7a5 100644 --- a/tests/causal_identifiers/test_complete_adjustment.py +++ b/tests/causal_identifiers/test_complete_adjustment.py @@ -6,6 +6,8 @@ def test_complete_adjsutment(): + # DAGs + G = MAG() G.add_edge("Z", "X", G.directed_edge_name) G.add_edge("Z", "Y", G.directed_edge_name) @@ -36,6 +38,8 @@ def test_complete_adjsutment(): assert not cad.adjustable(G, {"X"}, {"Y"}) + # CPDAGs + G = PAG() G.add_edge("I", "X", G.directed_edge_name) G.add_edge("Z", "X", G.directed_edge_name) @@ -56,6 +60,8 @@ def test_complete_adjsutment(): assert cad.adjustable(G, {"X"},{"Y"}) + # MAG + G = MAG() G.add_edge("A", "B", G.directed_edge_name) G.add_edge("B", "C", G.directed_edge_name) @@ -100,6 +106,21 @@ def test_complete_adjsutment(): assert cad.adjustable(G, {"A", "D"}, {"E"} ) + G = MAG() + G.add_edge("B", "A", G.directed_edge_name) + G.add_edge("C", "B", G.directed_edge_name) + G.add_edge("C", "D", G.directed_edge_name) + G.add_edge("E", "D", G.directed_edge_name) + G.add_edge("E", "F", G.directed_edge_name) + G.add_edge("F", "A", G.directed_edge_name) + G.add_edge("A", "D", G.directed_edge_name) + + cad = CompleteAdjustment() + + assert not cad.adjustable(G, {"A", "C"}, {"D"} ) + + # PAG + G = PAG() G.add_edge("A", "B", G.directed_edge_name) G.add_edge("B", "C", G.directed_edge_name) @@ -117,18 +138,6 @@ def test_complete_adjsutment(): assert cad.adjustable(G, {"A", "D"}, {"E"} ) - G = MAG() - G.add_edge("B", "A", G.directed_edge_name) - G.add_edge("C", "B", G.directed_edge_name) - G.add_edge("C", "D", G.directed_edge_name) - G.add_edge("E", "D", G.directed_edge_name) - G.add_edge("E", "F", G.directed_edge_name) - G.add_edge("F", "A", G.directed_edge_name) - G.add_edge("A", "D", G.directed_edge_name) - - cad = CompleteAdjustment() - - assert not cad.adjustable(G, {"A", "C"}, {"D"} ) From f2157ada91f407ab486ff3ded651ddbc9a32deca Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Sat, 13 Apr 2024 15:20:08 +0530 Subject: [PATCH 5/9] Added algorithm skeleton Signed-off-by: Aryan Roy --- .../causal_identifier/complete_adjustment.py | 70 ++++++++++++++++++- .../test_complete_adjustment.py | 36 +++++----- 2 files changed, 86 insertions(+), 20 deletions(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index 891782ce68..aa1c09634f 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -3,5 +3,71 @@ import pywhy_graphs class CompleteAdjustment: - def adjustable(G): - pass \ No newline at end of file + + def __init__(self, graph, x, y, z=None): + self._graph = graph + self._X = x + self._Y = y + if z is None: + self._Z = set() + else: + self._Z = z + + def adjustable(self, G): + #check amenability + if not self._is_amenable(): + return False + + #check if z contains any node from the forbidden set + + if not self._check_forbidden_set(): + return False + + #find the proper back-door graph + proper_back_door_graph = self._proper_backdoor_graph() + + #check if z m-seperates x and y in Gpbd + if not pywhy_graphs.m_seperated(proper_back_door_graph, self._X, self._Y, self._Z): + return False + + return True + + def _is_amenable(self): + dp = self._graph.directed_paths(self._X, self._Y) + pdp = pywhy_graphs.possibly_directed_paths(self._graph, dp) + ppdp = pywhy_graphs.proper_paths(self._graph, pdp) + visible_edges = frozenset(pywhy_graphs.get_visible_edges(self._graph, self._X)) + for elem in ppdp: + first_edge = elem[0] + if first_edge in visible_edges and first_edge[0] in self._X: + continue + else: + return False + return True + + def _check_forbidden_set(self): + forbidden_set = pywhy_graphs.find_forbidden_set(self._graph, self._X, self._Y) + if len(self._Z.intersection(forbidden_set)) > 0: + return False + else: + return True + + def _proper_backdoor_graph(self): + dp = self._graph.directed_paths(self._X, self._Y) + pdp = pywhy_graphs.possibly_directed_paths(self._graph, dp) + ppdp = pywhy_graphs.proper_paths(self._graph, pdp) + visible_edges = pywhy_graphs.get_visible_edges(self._graph) # assuming all are directed edges + x_vedges = [] + for elem in visible_edges: + if elem[0] in self._X: + x_vedges.append(elem) + x_vedges = frozenset(x_vedges) + all_edges = [] + for elem in ppdp: + all_edges.extend(elem) + all_edges = frozenset(all_edges) + to_remove = all_edges.intersection(x_vedges) + G = self._graph.copy() + for elem in to_remove: + G.remove_edge(elem[0], elem[1], G.directed_edge_name) + return G \ No newline at end of file diff --git a/tests/causal_identifiers/test_complete_adjustment.py b/tests/causal_identifiers/test_complete_adjustment.py index fd4533d7a5..b9240cd828 100644 --- a/tests/causal_identifiers/test_complete_adjustment.py +++ b/tests/causal_identifiers/test_complete_adjustment.py @@ -13,18 +13,18 @@ def test_complete_adjsutment(): G.add_edge("Z", "Y", G.directed_edge_name) G.add_edge("X", "Y", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"X"}, {"Y"}) - assert cad.adjustable(G, {"X"}, {"Y"}) + assert cad.adjustable() G = MAG() G.add_edge("X", "Z", G.directed_edge_name) G.add_edge("X", "Y", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"X"}, {"Y"}) - assert cad.adjustable(G, {"X"}, {"Y"}) + assert cad.adjustable() G = MAG() @@ -33,9 +33,9 @@ def test_complete_adjsutment(): G.add_edge("U", "X", G.directed_edge_name) G.add_edge("U", "Y", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"X"}, {"Y"}) - assert not cad.adjustable(G, {"X"}, {"Y"}) + assert not cad.adjustable() # CPDAGs @@ -56,9 +56,9 @@ def test_complete_adjsutment(): G.add_edge("A", "I", G.circle_edge_name) G.add_edge("I", "A", G.circle_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"X"},{"Y"}) - assert cad.adjustable(G, {"X"},{"Y"}) + assert cad.adjustable() # MAG @@ -71,9 +71,9 @@ def test_complete_adjsutment(): G.add_edge("F", "C", G.directed_edge_name) G.add_edge("F", "E", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"A", "D"}, {"E","F"}) - assert cad.adjustable(G, {"A", "D"}, {"E","F"}) + assert cad.adjustable() G = MAG() G.add_edge("A", "B", G.directed_edge_name) @@ -85,9 +85,9 @@ def test_complete_adjsutment(): G.add_edge("F", "E", G.directed_edge_name) G.add_edge("A", "F", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"A", "D"}, {"E","F"} ) - assert not cad.adjustable(G, {"A", "D"}, {"E","F"} ) + assert not cad.adjustable() G = MAG() @@ -102,9 +102,9 @@ def test_complete_adjsutment(): G.add_edge("H", "A", G.directed_edge_name) G.add_edge("I", "A", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"A", "D"}, {"E"} ) - assert cad.adjustable(G, {"A", "D"}, {"E"} ) + assert cad.adjustable() G = MAG() G.add_edge("B", "A", G.directed_edge_name) @@ -115,9 +115,9 @@ def test_complete_adjsutment(): G.add_edge("F", "A", G.directed_edge_name) G.add_edge("A", "D", G.directed_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"A", "C"}, {"D"}) - assert not cad.adjustable(G, {"A", "C"}, {"D"} ) + assert not cad.adjustable() # PAG @@ -134,9 +134,9 @@ def test_complete_adjsutment(): G.add_edge("A", "H", G.circle_edge_name) G.add_edge("A", "I", G.circle_edge_name) - cad = CompleteAdjustment() + cad = CompleteAdjustment(G, {"A", "D"}, {"E"} ) - assert cad.adjustable(G, {"A", "D"}, {"E"} ) + assert cad.adjustable() From 0857cd20dcd660781c405d4a1bd39de0dcf09ce2 Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Sat, 15 Jun 2024 16:50:16 +0530 Subject: [PATCH 6/9] Added the graph as an argument Signed-off-by: Aryan Roy --- dowhy/causal_identifier/complete_adjustment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index aa1c09634f..5e387bd7b1 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -33,7 +33,7 @@ def adjustable(self, G): return True def _is_amenable(self): - dp = self._graph.directed_paths(self._X, self._Y) + dp = self._graph.directed_paths(self._graph, self._X, self._Y) pdp = pywhy_graphs.possibly_directed_paths(self._graph, dp) ppdp = pywhy_graphs.proper_paths(self._graph, pdp) visible_edges = frozenset(pywhy_graphs.get_visible_edges(self._graph, self._X)) From 95743ec56ce1a8c0f21cfdf20458d1cf8499a2c7 Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Sat, 15 Jun 2024 16:55:44 +0530 Subject: [PATCH 7/9] Converted to functions Signed-off-by: Aryan Roy --- .../causal_identifier/complete_adjustment.py | 117 +++++++++--------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index 5e387bd7b1..15341b44f0 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -2,72 +2,69 @@ import pywhy_graphs -class CompleteAdjustment: +def adjustable(self, G, X, Y, Z=None): - def __init__(self, graph, x, y, z=None): - self._graph = graph - self._X = x - self._Y = y - if z is None: - self._Z = set() - else: - self._Z = z + if Z is None: + Z = set() - def adjustable(self, G): - #check amenability - if not self._is_amenable(): - return False - - #check if z contains any node from the forbidden set + #check amenability + if not self._is_amenable(): + return False + + #check if z contains any node from the forbidden set - if not self._check_forbidden_set(): - return False + if not self._check_forbidden_set(): + return False + + #find the proper back-door graph + proper_back_door_graph = self._proper_backdoor_graph() - #find the proper back-door graph - proper_back_door_graph = self._proper_backdoor_graph() + #check if z m-seperates x and y in Gpbd + if not pywhy_graphs.m_seperated(proper_back_door_graph, X, Y, Z): + return False + + return True - #check if z m-seperates x and y in Gpbd - if not pywhy_graphs.m_seperated(proper_back_door_graph, self._X, self._Y, self._Z): +def _is_amenable(G, X, Y): + dp = G.directed_paths(G, X, Y) + pdp = pywhy_graphs.possibly_directed_paths(G, dp) + ppdp = pywhy_graphs.proper_paths(G, pdp) + visible_edges = frozenset(pywhy_graphs.get_visible_edges(G, X)) + for elem in ppdp: + first_edge = elem[0] + if first_edge in visible_edges and first_edge[0] in X: + continue + else: return False - - return True + return True + +def _check_forbidden_set(G,X,Y,Z): + + if Z is None: + Z = set() - def _is_amenable(self): - dp = self._graph.directed_paths(self._graph, self._X, self._Y) - pdp = pywhy_graphs.possibly_directed_paths(self._graph, dp) - ppdp = pywhy_graphs.proper_paths(self._graph, pdp) - visible_edges = frozenset(pywhy_graphs.get_visible_edges(self._graph, self._X)) - for elem in ppdp: - first_edge = elem[0] - if first_edge in visible_edges and first_edge[0] in self._X: - continue - else: - return False + forbidden_set = pywhy_graphs.find_forbidden_set(G, X, Y) + if len(Z.intersection(forbidden_set)) > 0: + return False + else: return True - - def _check_forbidden_set(self): - forbidden_set = pywhy_graphs.find_forbidden_set(self._graph, self._X, self._Y) - if len(self._Z.intersection(forbidden_set)) > 0: - return False - else: - return True - def _proper_backdoor_graph(self): - dp = self._graph.directed_paths(self._X, self._Y) - pdp = pywhy_graphs.possibly_directed_paths(self._graph, dp) - ppdp = pywhy_graphs.proper_paths(self._graph, pdp) - visible_edges = pywhy_graphs.get_visible_edges(self._graph) # assuming all are directed edges - x_vedges = [] - for elem in visible_edges: - if elem[0] in self._X: - x_vedges.append(elem) - x_vedges = frozenset(x_vedges) - all_edges = [] - for elem in ppdp: - all_edges.extend(elem) - all_edges = frozenset(all_edges) - to_remove = all_edges.intersection(x_vedges) - G = self._graph.copy() - for elem in to_remove: - G.remove_edge(elem[0], elem[1], G.directed_edge_name) - return G \ No newline at end of file +def _proper_backdoor_graph(G,X,Y): + dp = G.directed_paths(X, Y) + pdp = pywhy_graphs.possibly_directed_paths(G, dp) + ppdp = pywhy_graphs.proper_paths(G, pdp) + visible_edges = pywhy_graphs.get_visible_edges(G) # assuming all are directed edges + x_vedges = [] + for elem in visible_edges: + if elem[0] in X: + x_vedges.append(elem) + x_vedges = frozenset(x_vedges) + all_edges = [] + for elem in ppdp: + all_edges.extend(elem) + all_edges = frozenset(all_edges) + to_remove = all_edges.intersection(x_vedges) + G = G.copy() + for elem in to_remove: + G.remove_edge(elem[0], elem[1], G.directed_edge_name) + return G \ No newline at end of file From f17170432dcdbc5ebe366247986ae8ae85583575 Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Mon, 26 Aug 2024 18:24:33 +0530 Subject: [PATCH 8/9] using actual API Signed-off-by: Aryan Roy --- dowhy/causal_identifier/complete_adjustment.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index 15341b44f0..ca99b37c2e 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -50,9 +50,7 @@ def _check_forbidden_set(G,X,Y,Z): return True def _proper_backdoor_graph(G,X,Y): - dp = G.directed_paths(X, Y) - pdp = pywhy_graphs.possibly_directed_paths(G, dp) - ppdp = pywhy_graphs.proper_paths(G, pdp) + ppdp = pywhy_graphs.pproper_possibly_directed_path(G, X,Y) visible_edges = pywhy_graphs.get_visible_edges(G) # assuming all are directed edges x_vedges = [] for elem in visible_edges: From b3060db0c35d1e1a576dac90f308bdcd502aec3e Mon Sep 17 00:00:00 2001 From: Aryan Roy Date: Mon, 26 Aug 2024 18:32:05 +0530 Subject: [PATCH 9/9] fixing typo Signed-off-by: Aryan Roy --- dowhy/causal_identifier/complete_adjustment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dowhy/causal_identifier/complete_adjustment.py b/dowhy/causal_identifier/complete_adjustment.py index ca99b37c2e..f2b5deec05 100644 --- a/dowhy/causal_identifier/complete_adjustment.py +++ b/dowhy/causal_identifier/complete_adjustment.py @@ -50,7 +50,7 @@ def _check_forbidden_set(G,X,Y,Z): return True def _proper_backdoor_graph(G,X,Y): - ppdp = pywhy_graphs.pproper_possibly_directed_path(G, X,Y) + ppdp = pywhy_graphs.proper_possibly_directed_path(G, X, Y) visible_edges = pywhy_graphs.get_visible_edges(G) # assuming all are directed edges x_vedges = [] for elem in visible_edges: