py-why / causal-learn

Causal Discovery in Python. It also includes (conditional) independence tests and score functions.
https://causal-learn.readthedocs.io/en/latest/
MIT License
1.04k stars 174 forks source link

How to construct a causallearn.graph.Graph object from an numpy array? #167

Closed ZehaoJin closed 4 months ago

ZehaoJin commented 4 months ago

I have a numpy array of adjacency matrix, such as

array=np.array([[0, 0, 0, 0, 0, 0, 0],
                [1, 0, 0, 0, 1, 0, 0],
                [0, 0, 0, 0, 0, 0, 0],
                [0, 0, 1, 0, 0, 0, 0],
                [1, 0, 1, 0, 0, 0, 0],
                [1, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 1, 0]])

and I would like to convert it to a causallearn graph object, such as DAG=array2DAG(array) such that is can be applicable to most of causallearn ultility functions, such as

CPDAG=dag2cpdag(DAG)
shd= SHD(ground_truth, CPDAG).get_shd()

What is the easiest way to make that array2DAG function? I was trying this: (simply assign the array to G.graph)

cg = CausalGraph(array.shape[0])
cg.G.graph=array
DAG=cg.G

but this didn't work.

ZehaoJin commented 4 months ago

Uhmm I hard coded it out by start with a fully connected graph, and then removing all edges, and then adding edges. Not the most elegant way, but seems to work.

def array2dag(array):
    num_nodes = array.shape[0]
    cg = CausalGraph(num_nodes)
    for i in range(num_nodes):
        for j in range(num_nodes):
            edge1 = cg.G.get_edge(cg.G.nodes[i], cg.G.nodes[j])
            if edge1 is not None:
                cg.G.remove_edge(edge1)

    for i in range(num_nodes):
        for j in range(num_nodes):
            if adjacency_matrix[i,j] == 1:
                cg.G.add_edge(Edge(cg.G.nodes[i], cg.G.nodes[j], Endpoint.TAIL, Endpoint.ARROW))

    DAG = cg.G
    return DAG
kunwuz commented 4 months ago

Yeah, that seems to do the job. We don't have an existing function to do this since the definition of the endpoints might vary in different cases, but it doesn't seem to be a very complicated procedure to transfer.