def admits_voi(cid: CID, decision: str, node: str) -> bool: """Return True if cid admits value of information for node. - A CID admits value of information for a node X if: i) X is not a descendant of the decision node, D. ii) X is d-connected to U given Fa_D \ {X}, where U ∈ U ∩ Desc(D) ("Agent Incentives: a Causal Perspective" by Everitt, Carey, Langlois, Ortega, and Legg, 2020) """ if len(cid.agents) > 1: raise Exception( f"This CID has {len(cid.agents)} agents. This incentive is currently only \ valid for CIDs with one agent.") if node not in cid.nodes: raise Exception(f"{node} is not present in the cid") if decision not in cid.nodes: raise Exception(f"{decision} is not present in the cid") if not cid.sufficient_recall(): raise Exception("Voi only implemented graphs with sufficient recall") if node in nx.descendants(cid, decision) or node == decision: return False cid2 = cid.copy_without_cpds() cid2.add_edge(node, decision) req_graph = requisite_graph(cid2) return node in req_graph.get_parents(decision)
def admits_ri(cid: CID, decision: str, node: str) -> bool: """ Return True if cid admits a response incentive on node. - A CID G admits a response incentive on X ∈ V \ {D} if and only if the reduced graph G* min has a directed path X --> D. ("Agent Incentives: a Causal Perspective" by Everitt, Carey, Langlois, Ortega, and Legg, 2020) """ if len(cid.agents) > 1: raise Exception( f"This CID has {len(cid.agents)} agents. This incentive is currently only \ valid for CIDs with one agent.") if node not in cid.nodes: raise Exception(f"{node} is not present in the cid") if decision not in cid.nodes: raise Exception(f"{decision} is not present in the cid") if not cid.sufficient_recall(): raise Exception("Voi only implemented graphs with sufficient recall") if node == decision: return False req_graph = requisite_graph(cid) if find_all_dir_paths(req_graph, node, decision): return True return False