Coverage for src/causalspyne/ancestral_acc.py: 86%

21 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-05-15 16:30 +0000

1""" 

2ancestral accuracy calculate the percentage of correct prediction 

3among all pairwise variables' ancestral relationships (binary) 

4""" 

5from itertools import combinations 

6import warnings 

7 

8from causalspyne.dag2ancestral import DAG2Ancestral 

9 

10 

11def ancestral_acc(true_dag, pred_order, list_hidden_nodes=None): 

12 """ 

13 Parameters: 

14 true_dag: Target causalspyne graph 

15 pred_order: 

16 ISSUE #34, the pairwise relationship can be + or - ancestral, but can also be no ancestral relationship 

17 list_hidden_nodes (list): list of nodes in DAG to hide, here we use pairwise combinations of pred_order, which 

18 already assumes the algorithm has a clear + order only.  

19 Returns: 

20 float: 

21 """ 

22 dag2ancestral = DAG2Ancestral(true_dag.mat_adjacency) 

23 dag2ancestral.pre_cal_n_hop() 

24 size_dag = true_dag.num_nodes 

25 if list_hidden_nodes is not None: 

26 n_vars = size_dag - len(list_hidden_nodes) 

27 else: 

28 n_vars = size_dag 

29 if n_vars != len(pred_order): 

30 warnings.warn(f"predicted causal order {pred_order} does not \ 

31 have the same number of observables!, hidden are: {list_hidden_nodes} \ 

32 now forcing number of variables to be the lengh of pred_order") 

33 n_vars = len(pred_order) 

34 

35 pairwise_combinations = list(combinations(pred_order, 2)) 

36 

37 n_correct = 0 

38 for pair in pairwise_combinations: 

39 ancestor, offspring = pair 

40 if dag2ancestral.is_ancestor(ancestor, offspring): 

41 n_correct += 1 

42 num_combos = n_vars * (n_vars - 1) /2 

43 return float(n_correct) / num_combos