@@ -291,6 +291,21 @@ def test_enumerate_minimal_adjustment_sets(self):
291291 adjustment_sets = causal_dag .enumerate_minimal_adjustment_sets (xs , ys )
292292 self .assertEqual ([{"Z" }], list (adjustment_sets ))
293293
294+ def test_identification_total_effect (self ):
295+ """Test whether identification works for total effect."""
296+ causal_dag = CausalDAG ()
297+ causal_dag .add_edges_from ([("X" , "M" ), ("M" , "Y" )])
298+
299+ self .assertEqual (
300+ set (), causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" , effect_type = "total" )
301+ )
302+
303+ def test_identification_invalid_effect (self ):
304+ causal_dag = CausalDAG ()
305+ with self .assertRaises (ValueError ) as e :
306+ causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" , effect_type = "invalid" )
307+ self .assertEqual (e .exception , f"Causal effect should be 'total' or 'direct', not 'invalid'." )
308+
294309 def test_enumerate_minimal_adjustment_sets_multiple (self ):
295310 """Test whether enumerate_minimal_adjustment_sets lists all minimum adjustment sets if multiple are possible."""
296311 causal_dag = CausalDAG ()
@@ -403,32 +418,48 @@ def test_list_all_min_sep(self):
403418 min_separators = set (frozenset (min_separator ) for min_separator in min_separators )
404419 self .assertEqual ({frozenset ({2 , 3 }), frozenset ({3 , 4 }), frozenset ({4 , 5 })}, min_separators )
405420
421+ def test_close_separator_exception (self ):
422+ g = nx .Graph ()
423+ g .add_edges_from ([("X" , "Y" )])
424+
425+ with self .assertRaises (ValueError ) as e :
426+ close_separator (
427+ graph = g ,
428+ treatment_node = "X" ,
429+ outcome_node = "X" ,
430+ treatment_node_set = {"Y" },
431+ )
432+ self .assertEqual (e .exception , "No X-Y separator in the graph." )
433+
406434
407435class TestHiddenVariableDAG (unittest .TestCase ):
408436 """
409437 Test the CausalDAG identification for the exclusion of hidden variables.
410438 """
411439
412- def setUp (self ) -> None :
413- self .temp_dir_path = tempfile .mkdtemp ()
414- self .dag_dot_path = os .path .join (self .temp_dir_path , "dag.dot" )
415- dag_dot = """digraph DAG { rankdir=LR; Z -> X; X -> M; M -> Y; Z -> M; }"""
416- with open (self .dag_dot_path , "w" ) as f :
417- f .write (dag_dot )
418-
419- def test_ignore_varaible_adjustment_sets (self ):
440+ def test_impossible_identification (self ):
420441 """Test whether identification produces different adjustment sets if nodes_to_ignore is set."""
421- causal_dag = CausalDAG (self . dag_dot_path )
422- adjustment_sets = causal_dag .identification ( treatment_variable = "X" , outcome_variable = "M" )
442+ causal_dag = CausalDAG ()
443+ causal_dag .add_edges_from ([( "X" , "M" ), ( "M" , "Y" ), ( "X" , "Y" )] )
423444
424- adjustment_sets_with_hidden = causal_dag .identification (
425- treatment_variable = "X" , outcome_variable = "M" , nodes_to_ignore = ["Z" ]
426- )
445+ self .assertEqual (causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" ), {"M" })
427446
428- self .assertNotEqual (adjustment_sets , adjustment_sets_with_hidden )
447+ with self .assertRaises (ValueError ) as e :
448+ causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" , nodes_to_ignore = ["M" ])
449+ self .assertEqual (
450+ e .exception ,
451+ "Could not find a suitable adjustment set for the direct effect of X on Y while avoiding nodes in set {M}." ,
452+ )
429453
430- def tearDown (self ) -> None :
431- shutil .rmtree (self .temp_dir_path )
454+ def test_adjustment_set_nodes_to_ignore (self ):
455+ """Test whether identification produces different adjustment sets if nodes_to_ignore is set."""
456+ causal_dag = CausalDAG ()
457+ causal_dag .add_edges_from ([("L" , "V" ), ("V" , "X" ), ("X" , "Y" ), ("L" , "C" ), ("C" , "Y" )])
458+
459+ self .assertEqual (causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" ), {"C" })
460+ self .assertEqual (
461+ causal_dag .identification (treatment_variable = "X" , outcome_variable = "Y" , nodes_to_ignore = {"C" }), {"L" }
462+ )
432463
433464
434465def time_it (label , func , * args , ** kwargs ):
0 commit comments