causal-learn
causal-learn copied to clipboard
Add required edges by background knowledge
Hi, Thanks for your great work.
I hope to add an edge that is not detected during the PC skeleton phase according to background knowledge. I read the codes in causal-learn/causallearn/utils/PCUtils/BackgroundKnowledgeOrientUtils.py and it looks like only edges already detected in the skeleton phase can be defined as 'required'.
Is there any method to solve my problem? Can I direct add the following lines in BackgroundKnowledgeOrientUtils.py?
def orient_by_background_knowledge(cg: CausalGraph, background_knowledge: BackgroundKnowledge):
"""
orient the direction of edges using background background_knowledge after running skeleton_discovery in PC algorithm
Parameters
----------
cg: a CausalGraph object. Where cg.G.graph[j,i]=1 and cg.G.graph[i,j]=-1 indicates i -> j ,
cg.G.graph[i,j] = cg.G.graph[j,i] = -1 indicates i -- j,
cg.G.graph[i,j] = cg.G.graph[j,i] = 1 indicates i <-> j.
background_knowledge: artificial background background_knowledge
Returns
-------
"""
if type(cg) != CausalGraph or (type(background_knowledge) != BackgroundKnowledge and type(background_knowledge) != CustomBackgroundKnowledge):
raise TypeError(
'cg must be type of CausalGraph and background_knowledge must be type of BackgroundKnowledge. cg = ' + str(
type(cg)) + ' background_knowledge = ' + str(type(background_knowledge)))
for edge in cg.G.get_graph_edges():
if cg.G.is_undirected_from_to(edge.get_node1(), edge.get_node2()):
if background_knowledge.is_forbidden(edge.get_node2(), edge.get_node1()):
cg.G.remove_edge(edge)
cg.G.add_directed_edge(edge.get_node1(), edge.get_node2())
elif background_knowledge.is_forbidden(edge.get_node1(), edge.get_node2()):
cg.G.remove_edge(edge)
cg.G.add_directed_edge(edge.get_node2(), edge.get_node1())
elif background_knowledge.is_required(edge.get_node2(), edge.get_node1()):
cg.G.remove_edge(edge)
cg.G.add_directed_edge(edge.get_node2(), edge.get_node1())
elif background_knowledge.is_required(edge.get_node1(), edge.get_node2()):
cg.G.remove_edge(edge)
cg.G.add_directed_edge(edge.get_node1(), edge.get_node2())
# custom change to add required edges
for node1 in cg.G.get_nodes():
for node2 in cg.G.get_nodes():
if not cg.G.is_undirected_from_to(node1,node2):
if background_knowledge.is_required(node1,node2):
cg.G.add_directed_edge(node1,node2)
elif background_knowledge.is_required(node2,node1):
cg.G.add_directed_edge(node2,node1)
Hi, unfortunately, we don't have the functionality you described for now. We're not sure about the custom changes now, but we will try and see whether it's plausible.