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
def admits_dir_voc(cid: CID, decision: str, node: str) -> bool: """ Return True if a single-decision cid admits direct positive value of control for node. - A single-decision CID G admits positive value of control for a node X ∈ V \ {D} if and only if there is a directed path X --> U in the reduced graph G∗. - The path X --> U may or may not pass through D. - The agent has a direct value of control incentive on D if the path does not pass through D. - The agent has an indirect value of control incentive on D if the path does pass through D and there is also a backdoor path X--U that begins backwards from X (...<- X) and is active when conditioning on Fa_D \ {X} """ 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") agent_utilities = cid.all_utility_nodes req_graph = requisite_graph(cid) if not admits_voc(cid, decision, node): return False for util in agent_utilities: if node == util or util in nx.descendants(req_graph, node): x_u_paths = find_all_dir_paths(req_graph, node, util) if any([decision not in path for path in x_u_paths]): return True return False
def test_requisite_graph(self) -> None: cid = get_trim_example_cid() self.assertFalse(requisite(cid, 'D2', 'D1')) self.assertTrue(requisite(cid, 'D2', 'Y2')) self.assertCountEqual(cid.get_parents('D2'), ['Y1', 'Y2', 'D1', 'Z1', 'Z2']) self.assertEqual(len(cid.edges), 12) req_graph = requisite_graph(cid) self.assertEqual(len(req_graph.edges), 7) self.assertCountEqual(req_graph.get_parents('D2'), ['Y2'])
def admits_ri(cid: CID, decision: str, node: str) -> bool: """ Return True if a single-decision cid admits a response incentive on node. - A single decision 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 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 node == decision: return False req_graph = requisite_graph(cid) if find_all_dir_paths(req_graph, node, decision): return True return False
def admits_voc(cid: CID, decision: str, node: str) -> bool: """ Return True if a single-decision cid admits positive value of control for node. - A single-decision CID G admits positive value of control for a node X ∈ V \ {D} if and only if there is a directed path X --> U in the reduced graph G∗. """ req_graph = requisite_graph(cid) agent_utilities = cid.all_utility_nodes 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 node == decision: return False for util in agent_utilities: if node == util or util in nx.descendants(req_graph, node): return True return False