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 _effective_dir_path_exists(mb: MACIDBase, start: str, finish: str, effective_set: List[str]) -> bool: """ checks whether an effective directed path exists """ start_finish_paths = find_all_dir_paths(mb, start, finish) for path in start_finish_paths: if _path_is_effective(mb, path, effective_set): return True else: return False
def _directed_effective_path_not_through_set_y(mb: MACIDBase, start: str, finish: str, effective_set: List[str], y: List[str] = []) -> bool: """ checks whether a directed effective path exists that doesn't pass through any of the nodes in the set y. """ start_finish_paths = find_all_dir_paths(mb, start, finish) for path in start_finish_paths: path_not_through_y = set(y).isdisjoint(set(path)) if _path_is_effective(mb, path, effective_set) and path_not_through_y: return True else: return False
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 test_find_all_dir_paths(self) -> None: example = MACID([ ('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('B', 'F'), ('F', 'E')], {1: {'D': ['D'], 'U': ['E']}}) self.assertEqual(find_all_dir_paths(example, 'A', 'E'), [['A', 'B', 'C', 'D', 'E'], ['A', 'B', 'F', 'E']]) self.assertEqual(find_all_dir_paths(example, 'C', 'E'), [['C', 'D', 'E']]) self.assertFalse(find_all_dir_paths(example, 'F', 'A')) self.assertTrue(len(find_all_dir_paths(example, 'B', 'E')) == 2) with self.assertRaises(Exception): find_all_dir_paths(example, 'U2', 'A')
def admits_ici(cid: CID, decision: str, node: str) -> bool: """ Return True if a single-decision cid admits an instrumental control incentive on node. - A single-decision CID G admits an instrumental control incentive on X ∈ V if and only if G has a directed path from the decision D to a utility node U ∈ U that passes through X, i.e. a directed path D --> X --> U. """ 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 d_u_paths = [ path for util in agent_utilities for path in find_all_dir_paths(cid, decision, util) ] if any(node in path for path in d_u_paths): return True return False