def basic_different_dec_cardinality() -> MACID: """A basic MACIM where the cardinality of each agent's decision node is different. It has one subgame perfect NE. """ macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1, 2]) agent1_payoff = np.array([[3, 1, 0], [1, 2, 3]]) agent2_payoff = np.array([[1, 2, 1], [1, 0, 3]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d1, d2], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d1, d2], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def basic2agent_tie_break() -> MACID: macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) cpd_u1 = TabularCPD('U1', 6, np.array([[0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), evidence=['D1', 'D2'], evidence_card=[2, 2]) cpd_u2 = TabularCPD('U2', 6, np.array([[0, 0, 0, 0], [1, 0, 0, 0], [0, 0, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0]]), evidence=['D1', 'D2'], evidence_card=[2, 2]) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def basic_different_dec_cardinality() -> MACID: macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1, 2]) cpd_u1 = TabularCPD('U1', 4, np.array([[0, 0, 1, 0, 0, 0], [0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 1]]), evidence=['D1', 'D2'], evidence_card=[2, 3]) cpd_u2 = TabularCPD('U2', 4, np.array([[0, 0, 0, 0, 1, 0], [1, 0, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1]]), evidence=['D1', 'D2'], evidence_card=[2, 3]) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def modified_taxi_competition() -> MACID: """ Modifying the payoffs in the taxi competition example so that there is a tie break (if taxi 1 chooses to stop in front of the expensive hotel, taxi 2 is indifferent between their choices.) - There are now two SPNE D1 +----------+----------+----------+ | taxi 1 | expensive| cheap | +----------+----------+----------+ |expensive | 2 | 3 | D2 +----------+----------+----------+ | cheap | 5 | 1 | +----------+----------+----------+ D1 +----------+----------+----------+ | taxi 2 | expensive| cheap | +----------+----------+----------+ |expensive | 2 | 5 | D2 +----------+----------+----------+ | cheap | 3 | 5 | +----------+----------+----------+ """ macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) d1_domain = ['e', 'c'] d2_domain = ['e', 'c'] cpd_d1 = DecisionDomain('D1', d1_domain) cpd_d2 = DecisionDomain('D2', d2_domain) agent1_payoff = np.array([[2, 3], [5, 1]]) agent2_payoff = np.array([[2, 5], [3, 5]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d2_domain.index(d2), d1_domain.index(d1)], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d2_domain.index(d2), d1_domain.index(d1)], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def taxi_competition() -> MACID: """ A MACIM for the "Taxi Competition" example introduced in "Equilibrium Refinements for Multi-Agent Influence Diagrams: Theory and Practice" by Hammond, Fox, Everitt, Abate & Wooldridge, 2021: D1 +----------+----------+----------+ | taxi 1 | expensive| cheap | +----------+----------+----------+ |expensive | 2 | 3 | D2 +----------+----------+----------+ | cheap | 5 | 1 | +----------+----------+----------+ D1 +----------+----------+----------+ | taxi 2 | expensive| cheap | +----------+----------+----------+ |expensive | 2 | 5 | D2 +----------+----------+----------+ | cheap | 3 | 1 | +----------+----------+----------+ - There are 3 pure startegy NE and 1 pure SPE. """ macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) d1_domain = ['e', 'c'] d2_domain = ['e', 'c'] cpd_d1 = DecisionDomain('D1', d1_domain) cpd_d2 = DecisionDomain('D2', d2_domain) agent1_payoff = np.array([[2, 3], [5, 1]]) agent2_payoff = np.array([[2, 5], [3, 1]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d2_domain.index(d2), d1_domain.index(d1)], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d2_domain.index(d2), d1_domain.index(d1)], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def battle_of_the_sexes() -> MACID: """ This macim is a representation of the battle of the sexes game (also known as Bach or Stravinsky). It is a simultaneous symmetric two-player game with payoffs corresponding to the following normal form game - the row player is Female and the column player is Male: +----------+----------+----------+ | |Opera | Football | +----------+----------+----------+ | Opera | 3, 2 | 0, 0 | +----------+----------+----------+ | Football | 0, 0 | 2, 3 | +----------+----------+----------+ - This game has two pure NE: (Opera, Football) and (Football, Opera) """ macid = MACID([('D_F', 'U_F'), ('D_F', 'U_M'), ('D_M', 'U_M'), ('D_M', 'U_F')], { 'M': { 'D': ['D_F'], 'U': ['U_F'] }, 'F': { 'D': ['D_M'], 'U': ['U_M'] } }) d_f_domain = ['O', 'F'] d_m_domain = ['O', 'F'] cpd_d_f = DecisionDomain('D_F', d_f_domain) cpd_d_m = DecisionDomain('D_M', d_m_domain) agent_f_payoff = np.array([[3, 0], [0, 2]]) agent_m_payoff = np.array([[2, 0], [0, 3]]) cpd_u_f = FunctionCPD( 'U_F', lambda d_f, d_m: agent_f_payoff[d_f_domain.index(d_f), d_m_domain.index(d_m)], evidence=['D_F', 'D_M']) cpd_u_m = FunctionCPD( 'U_M', lambda d_f, d_m: agent_m_payoff[d_f_domain.index(d_f), d_m_domain.index(d_m)], evidence=['D_F', 'D_M']) macid.add_cpds(cpd_d_f, cpd_d_m, cpd_u_f, cpd_u_m) return macid
def test_get_reasoning_patterns(self) -> None: macid = MACID([('D1', 'U'), ('D2', 'D1')], {1: { 'D': ['D1', 'D2'], 'U': ['U'] }}) self.assertEqual(get_reasoning_patterns(macid)['dir_effect'], ['D1']) macid2 = MACID([('D1', 'U2'), ('D1', 'D2'), ('D2', 'U1'), ('D2', 'U2')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) self.assertEqual(get_reasoning_patterns(macid2)['dir_effect'], ['D2']) self.assertEqual(get_reasoning_patterns(macid2)['manip'], ['D1']) macid3 = MACID([('X', 'U1'), ('X', 'U2'), ('X', 'D1'), ('D1', 'D2'), ('D2', 'U1'), ('D2', 'U2')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) self.assertEqual(get_reasoning_patterns(macid3)['dir_effect'], ['D2']) self.assertEqual(get_reasoning_patterns(macid3)['sig'], ['D1']) macid4 = MACID([('D1', 'X2'), ('X1', 'X2'), ('X2', 'D2'), ('D2', 'U1'), ('D2', 'U2'), ('X1', 'U2')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) self.assertEqual(get_reasoning_patterns(macid4)['dir_effect'], ['D2']) self.assertEqual(get_reasoning_patterns(macid4)['rev_den'], ['D1'])
def two_agents_three_actions() -> MACID: """ This macim is a representation of a game where two players must decide between threee different actions simultaneously - the row player is agent 1 and the column player is agent 2 - the normal form representation of the payoffs is as follows: +----------+----------+----------+----------+ | | L | C | R | +----------+----------+----------+----------+ | T | 4, 3 | 5, 1 | 6, 2 | +----------+----------+----------+----------+ | M | 2, 1 | 8, 4 | 3, 6 | +----------+----------+----------+----------+ | B | 3, 0 | 9, 6 | 2, 8 | +----------+----------+----------+----------+ - The game has one pure NE (T,L) """ macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) d1_domain = ['T', 'M', 'B'] d2_domain = ['L', 'C', 'R'] cpd_d1 = DecisionDomain('D1', d1_domain) cpd_d2 = DecisionDomain('D2', d2_domain) agent1_payoff = np.array([[4, 5, 6], [2, 8, 3], [3, 9, 2]]) agent2_payoff = np.array([[3, 1, 2], [1, 4, 6], [0, 6, 8]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def get_path_example() -> MACID: macid = MACID([('X1', 'X3'), ('X1', 'D'), ('X2', 'D'), ('X2', 'U'), ('D', 'U')], {1: { 'D': ['D'], 'U': ['U'] }}) return macid
def matching_pennies() -> MACID: """ This macim is a representation of the matching pennies game. It is symmetric two-player game with payoffs corresponding to the following normal form game - the row player is agent 1 and the column player is agent 2: +----------+----------+----------+ | |Heads | Tails | +----------+----------+----------+ | Heads | +1, -1 | -1, +1 | +----------+----------+----------+ | Tails | -1, +1 | +1, -1 | +----------+----------+----------+ - This game has no pure NE, but has a mixed NE where each player chooses Heads or Tails with equal probability. """ macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) d1_domain = ['H', 'T'] d2_domain = ['H', 'T'] cpd_d1 = DecisionDomain('D1', d1_domain) cpd_d2 = DecisionDomain('D2', d2_domain) agent1_payoff = np.array([[1, -1], [-1, 1]]) agent2_payoff = np.array([[-1, 1], [1, -1]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def prisoners_dilemma() -> MACID: """ This macim is a representation of the canonical prisoner's dilemma. It is a simultaneous symmetric two-player game with payoffs corresponding to the following normal form game - the row player is agent 1 and the column player is agent 2: +----------+----------+----------+ | |Cooperate | Defect | +----------+----------+----------+ |Cooperate | -1, -1 | -3, 0 | +----------+----------+----------+ | Defect | 0, -3 | -2, -2 | +----------+----------+----------+ - This game has one pure NE: (defect, defect) """ macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) d1_domain = ['c', 'd'] d2_domain = ['c', 'd'] cpd_d1 = DecisionDomain('D1', d1_domain) cpd_d2 = DecisionDomain('D2', d2_domain) agent1_payoff = np.array([[-1, -3], [0, -2]]) agent2_payoff = np.transpose(agent1_payoff) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d1_domain.index(d1), d2_domain.index(d2)], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def signal() -> MACID: macid = MACID([('X', 'D1'), ('X', 'U2'), ('X', 'U1'), ('D1', 'U2'), ('D1', 'U1'), ('D1', 'D2'), ('D2', 'U1'), ('D2', 'U2')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_x = TabularCPD('X', 2, np.array([[.5], [.5]])) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D1', [0, 1]) u1_cpd_array = np.array([[0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0]]) u2_cpd_array = np.array([[0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0]]) cpd_u1 = TabularCPD('U1', 6, u1_cpd_array, evidence=['X', 'D1', 'D2'], evidence_card=[2, 2, 2]) cpd_u2 = TabularCPD('U2', 6, u2_cpd_array, evidence=['X', 'D1', 'D2'], evidence_card=[2, 2, 2]) macid.add_cpds(cpd_x, cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def test_direct_effect(self) -> None: macid = MACID([('D1', 'U'), ('D2', 'D1')], {1: { 'D': ['D1', 'D2'], 'U': ['U'] }}) self.assertTrue(direct_effect(macid, 'D1')) self.assertFalse(direct_effect(macid, 'D2')) with self.assertRaises(Exception): direct_effect(macid, 'D3')
def two_agent_two_pne() -> MACID: """ This macim is a simultaneous two player game and has a parameterisation that corresponds to the following normal form game - where the row player is agent 0, and the column player is agent 1 +----------+----------+----------+ | | Act(0) | Act(1) | +----------+----------+----------+ | Act(0) | 1, 1 | 4, 2 | +----------+----------+----------+ | Act(1) | 2, 4 | 3, 3 | +----------+----------+----------+ """ macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) cpd_u1 = TabularCPD('U1', 5, np.array([[0, 0, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 1, 0, 0]]), evidence=['D1', 'D2'], evidence_card=[2, 2]) cpd_u2 = TabularCPD('U2', 5, np.array([[0, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]), evidence=['D1', 'D2'], evidence_card=[2, 2]) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def umbrella() -> MACID: macid = MACID([('W', 'F'), ('W', 'A'), ('F', 'UM'), ('UM', 'A')], {1: { 'D': ['UM'], 'U': ['A'] }}) cpd_w = TabularCPD('W', 2, np.array([[.6], [.4]])) cpd_f = TabularCPD('F', 2, np.array([[.8, .3], [.2, .7]]), evidence=['W'], evidence_card=[2]) cpd_um = DecisionDomain('UM', [0, 1]) cpd_a = TabularCPD('A', 3, np.array([[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 0, 1]]), evidence=['W', 'UM'], evidence_card=[2, 2]) macid.add_cpds(cpd_w, cpd_f, cpd_um, cpd_a) return macid
def two_agent_one_pne() -> MACID: """ This macim is a simultaneous two player game and has a parameterisation that corresponds to the following normal form game - where the row player is agent 1, and the column player is agent 2 +----------+----------+----------+ | | Act(0) | Act(1) | +----------+----------+----------+ | Act(0) | 1, 2 | 3, 0 | +----------+----------+----------+ | Act(1) | 0, 3 | 2, 2 | +----------+----------+----------+ """ macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) agent1_payoff = np.array([[1, 3], [0, 2]]) agent2_payoff = np.array([[2, 0], [3, 2]]) cpd_u1 = FunctionCPD('U1', lambda d1, d2: agent1_payoff[d1, d2], evidence=['D1', 'D2']) cpd_u2 = FunctionCPD('U2', lambda d1, d2: agent2_payoff[d1, d2], evidence=['D1', 'D2']) macid.add_cpds(cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
def get_basic2agent_acyclic() -> MACID: macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) return macid
def sequential() -> MACID: macid = MACID([('D1', 'U1'), ('D1', 'U2'), ('D1', 'D2'), ('D2', 'U1'), ('D2', 'U2')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) return macid
def test_find_all_undir_paths(self) -> None: example = get_3node_cid() self.assertTrue(len(find_all_undir_paths(example, 'S', 'U')) == 2) with self.assertRaises(Exception): find_all_undir_paths(example, 'S', 'A') example2 = MACID([ ('X1', 'D'), ('X2', 'U')], {1: {'D': ['D'], 'U': ['U']}}) self.assertEqual(find_all_undir_paths(example2, 'X1', 'D'), [['X1', 'D']]) self.assertFalse(find_all_undir_paths(example2, 'X1', 'U')) example3 = MACID([ ('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E'), ('B', 'F'), ('F', 'E')], {1: {'D': ['D'], 'U': ['E']}}) self.assertCountEqual(find_all_undir_paths(example3, 'F', 'A'), [['F', 'E', 'D', 'C', 'B', 'A'], ['F', 'B', 'A']])
def politician() -> MACID: macid = MACID([('D1', 'I'), ('T', 'I'), ('T', 'U2'), ('I', 'D2'), ('R', 'D2'), ('D2', 'U1'), ('D2', 'U2')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) return macid
def forgetful_movie_star() -> MACID: macid = MACID( [('S', 'D11'), ('S', 'D12'), ('D2', 'U2'), ('D2', 'U11'), ('D11', 'U2'), ('D11', 'U11'), ('D11', 'U12'), ('D12', 'U12')], { 1: { 'D': ['D11', 'D12'], 'U': ['U11', 'U12'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) return macid
def c2d() -> MACID: macid = MACID([('C1', 'U1'), ('C1', 'U2'), ('C1', 'D1'), ('D1', 'U1'), ('D1', 'U2'), ('D1', 'D2'), ('D2', 'U1'), ('D2', 'U2'), ('C1', 'D2')], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] } }) cpd_c1 = TabularCPD('C1', 2, np.array([[.5], [.5]])) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) cpd_u1 = TabularCPD('U1', 4, np.array([[0, 0, 0, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0], [0, 1, 0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1]]), evidence=['C1', 'D1', 'D2'], evidence_card=[2, 2, 2]) cpd_u2 = TabularCPD('U2', 6, np.array([[0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0]]), evidence=['C1', 'D1', 'D2'], evidence_card=[2, 2, 2]) macid.add_cpds(cpd_c1, cpd_d1, cpd_d2, cpd_u1, cpd_u2) return macid
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 subgame_difference() -> MACID: macid = MACID( [('N', 'D1'), ('N', 'U1_A'), ('N', 'U2_A'), ('D1', 'U1_A'), ('D1', 'U2_A'), ('D1', 'U1_B'), ('D1', 'U2_B'), ('D1', 'D2'), ('D2', 'U1_B'), ('D2', 'U2_B')], { 1: { 'D': ['D1'], 'U': ['U1_A', 'U1_B'] }, 2: { 'D': ['D2'], 'U': ['U2_A', 'U2_B'] } }) return macid
def tree_doctor() -> MACID: macid = MACID( [('PT', 'E'), ('PT', 'TS'), ('PT', 'BP'), ('TS', 'TDoc'), ('TS', 'TDead'), ('TDead', 'V'), ('TDead', 'Tree'), ('TDoc', 'TDead'), ('TDoc', 'Cost'), ('TDoc', 'BP'), ('BP', 'V')], { 0: { 'D': ['PT', 'BP'], 'U': ['E', 'V'] }, 1: { 'D': ['TDoc'], 'U': ['Tree', 'Cost'] } }) return macid
def revealing_or_denying(macid: MACID, decision: str, effective_set: List[str]) -> bool: """checks to see whether this decision is motivated by an incentive for revealing or denying Graphical Criterion: 1) There is a directed decision-free path from D_A to an effective decision node D_B. 2) There is a direced, effective path from D_B to U_A. 3) There is an effective indirect front-door path π from D_A to U_B that is not blocked by D_B U W^{D_A}_{D_B}. """ if decision not in macid.nodes: raise Exception(f"{decision} is not present in the macid") if not all([node in macid.nodes for node in effective_set]): raise Exception( "One or many of the nodes in the effective_set are not present in the macid." ) agent = macid.whose_node[decision] agent_utils = macid.utility_nodes_agent[agent] reachable_decisions = [] # set of possible D_B list_decs = copy.deepcopy(macid.all_decision_nodes) list_decs.remove(decision) for dec_reach in list_decs: if dec_reach in effective_set: if directed_decision_free_path(macid, decision, dec_reach): reachable_decisions.append(dec_reach) for decision_b in reachable_decisions: agent_b = macid.whose_node[decision_b] agent_b_utils = macid.utility_nodes_agent[agent_b] for u in agent_utils: if _effective_dir_path_exists(macid, decision_b, u, effective_set): for u_b in agent_b_utils: decision_b_parents_not_desc_decision = [ node for node in macid.get_parents(decision_b) if node not in set(nx.descendants(macid, decision)) ] cond_nodes = [decision_b ] + decision_b_parents_not_desc_decision if is_active_indirect_frontdoor_trail( macid, decision, u_b, cond_nodes): return True else: return False
def test_direct_value_of_control(self) -> None: cid = get_fitness_tracker() self.assertFalse(admits_dir_voc(cid, 'TF')) self.assertTrue(admits_dir_voc(cid, 'F')) self.assertCountEqual(admits_dir_voc_list(cid), ['F', 'P']) with self.assertRaises(Exception): admits_dir_voc(cid, 'B') macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], {0: {'D': ['D1'], 'U': ['U1']}, 1: {'D': ['D2'], 'U': ['U2']}}) with self.assertRaises(Exception): admits_dir_voc(macid, 'D2') with self.assertRaises(Exception): admits_dir_voc_list(macid)
def triage() -> MACID: macid = MACID( [('H1', 'D1'), ('H1', 'U1'), ('H2', 'D2'), ('H2', 'U2'), ('D1', 'U1'), ('D1', 'U2'), ('D1', 'D3'), ('D1', 'D4'), ('D1', 'U3'), ('D1', 'U4'), ('D2', 'U1'), ('D2', 'U2'), ('D2', 'D4'), ('D2', 'D3'), ('D2', 'U3'), ('D2', 'U4'), ('H3', 'D3'), ('H3', 'U3'), ('H4', 'D4'), ('H4', 'U4'), ('D3', 'U3'), ('D3', 'U4'), ('D3', 'U1'), ('D3', 'U2'), ('D4', 'U3'), ('D4', 'U4'), ('D4', 'U1'), ('D4', 'U2'), ('D3', 'U5'), ('D3', 'U6'), ('D4', 'U5'), ('D4', 'U6'), ('D1', 'U5'), ('D1', 'U6'), ('D2', 'U5'), ('D2', 'U6'), ('H5', 'D5'), ('H5', 'U5'), ('H6', 'D6'), ('H6', 'U6'), ('D1', 'D5'), ('D1', 'D6'), ('D2', 'D5'), ('D2', 'D6'), ('D3', 'D5'), ('D3', 'D6'), ('D4', 'D5'), ('D4', 'D6'), ('D5', 'U3'), ('D5', 'U4'), ('D5', 'U1'), ('D5', 'U2'), ('D5', 'U5'), ('D5', 'U6'), ('D6', 'U3'), ('D6', 'U4'), ('D6', 'U1'), ('D6', 'U2'), ('D6', 'U5'), ('D6', 'U6')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] }, 3: { 'D': ['D3'], 'U': ['U3'] }, 4: { 'D': ['D4'], 'U': ['U4'] }, 5: { 'D': ['D5'], 'U': ['U5'] }, 6: { 'D': ['D6'], 'U': ['U6'] } }) return macid
def test_revealing_or_denying(self) -> None: macid = MACID([('D1', 'X2'), ('X1', 'X2'), ('X2', 'D2'), ('D2', 'U1'), ('D2', 'U2'), ('X1', 'U2')], { 1: { 'D': ['D1'], 'U': ['U1'] }, 2: { 'D': ['D2'], 'U': ['U2'] } }) effective_set = ['D2'] # by direct effect self.assertTrue(revealing_or_denying(macid, 'D1', effective_set)) self.assertFalse(revealing_or_denying(macid, 'D2', effective_set)) with self.assertRaises(Exception): revealing_or_denying(macid, 'D3', effective_set) effective_set2 = ['A'] with self.assertRaises(Exception): revealing_or_denying(macid, 'D1', effective_set2)
def test_instrumental_control_incentive(self) -> None: cid = get_content_recommender() self.assertTrue(admits_ici(cid, 'P', 'I')) self.assertFalse(admits_ici(cid, 'P', 'O')) self.assertCountEqual(admits_ici_list(cid, 'P'), ['I', 'P', 'C']) with self.assertRaises(Exception): admits_ici(cid, 'P', 'A') with self.assertRaises(Exception): admits_ici(cid, 'B', 'O') macid = MACID([('D1', 'D2'), ('D1', 'U1'), ('D1', 'U2'), ('D2', 'U2'), ('D2', 'U1')], {0: {'D': ['D1'], 'U': ['U1']}, 1: {'D': ['D2'], 'U': ['U2']}}) with self.assertRaises(Exception): admits_ici(macid, 'D2', 'D1') with self.assertRaises(Exception): admits_ici_list(macid, 'D2')