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 get_insufficient_recall_cid() -> CID: cid = CID([('A', 'U'), ('B', 'U')], decision_nodes=['A', 'B'], utility_nodes=['U']) cid.add_cpds(DecisionDomain('A', [0, 1]), DecisionDomain('B', [0, 1]), FunctionCPD('U', lambda a, b: a * b, evidence=['A', 'B'])) return cid
def get_sequential_cid() -> CID: """ This CID is a subtle case of sufficient recall, as the strategy for D1 influences the expected utility of D2, but D2 can still be chosen without knowing D1, since D1 does not influence any utility nodes descending from D2. """ cid = CID([ ('S1', 'D1'), ('D1', 'U1'), ('S1', 'U1'), ('D1', 'S2'), ('S2', 'D2'), ('D2', 'U2'), ('S2', 'U2'), ], decision_nodes=['D1', 'D2'], utility_nodes=['U1', 'U2']) cid.add_cpds( UniformRandomCPD('S1', [0, 1]), DecisionDomain('D1', [0, 1]), FunctionCPD('U1', lambda s1, d1: int(s1 == d1), evidence=['S1', 'D1']), FunctionCPD('S2', lambda d1: d1, evidence=['D1']), DecisionDomain('D2', [0, 1]), FunctionCPD('U2', lambda s2, d2: int(s2 == d2), evidence=['S2', 'D2']), ) return cid
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 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 get_insufficient_recall_cid() -> CID: cid = CID([('A', 'U'), ('B', 'U')], decision_nodes=['A', 'B'], utility_nodes=['U']) cpd_u = TabularCPD('U', 2, np.random.randn(2, 4), evidence=['A', 'B'], evidence_card=[2, 2]) cid.add_cpds(DecisionDomain('A', [0, 1]), DecisionDomain('B', [0, 1]), cpd_u) return cid
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 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_2dec_cid() -> CID: cid = CID([('S1', 'S2'), ('S1', 'D1'), ('D1', 'S2'), ('S2', 'U'), ('S2', 'D2'), ('D2', 'U')], decision_nodes=['D1', 'D2'], utility_nodes=['U']) cpd_s1 = UniformRandomCPD('S1', [0, 1]) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) cpd_s2 = FunctionCPD('S2', lambda s2, d1: int(s2 == d1), evidence=['S1', 'D1']) cpd_u = FunctionCPD('U', lambda s2, d2: int(s2 == d2), evidence=['S2', 'D2']) cid.add_cpds(cpd_s1, cpd_d1, cpd_s2, cpd_d2, cpd_u) return cid
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 get_3node_cid() -> CID: cid = CID([('S', 'D'), ('S', 'U'), ('D', 'U')], decision_nodes=['D'], utility_nodes=['U']) cpd_s = UniformRandomCPD('S', [0, 1]) cpd_u = FunctionCPD('U', lambda s, d: int(s == d), evidence=['S', 'D']) cpd_d = DecisionDomain('D', [0, 1]) cid.add_cpds(cpd_d, cpd_s, cpd_u) return cid
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 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 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 make_decision(self, node: str, agent: Union[str, int] = 0) -> None: """"Turn a chance or utility node into a decision node.""" if hasattr(self, "cpds") and isinstance(self.get_cpds(node), DecisionDomain): pass elif hasattr(self, "cpds") and not isinstance(self.get_cpds(node), DecisionDomain): cpd_new = DecisionDomain(node, self.get_cpds(node).state_names[node]) self.decision_nodes_agent[agent].append(node) self.whose_node[node] = agent self.add_cpds(cpd_new) else: raise Exception(f"node {node} has not yet been assigned a domain.")
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 get_5node_cid_with_scaled_utility() -> CID: cid = CID([('S1', 'D'), ('S1', 'U1'), ('S2', 'D'), ('S2', 'U2'), ('D', 'U1'), ('D', 'U2')], decision_nodes=['D'], utility_nodes=['U1', 'U2']) cpd_s1 = UniformRandomCPD('S1', [0, 1]) cpd_s2 = UniformRandomCPD('S2', [0, 1]) cpd_u1 = FunctionCPD('U1', lambda s1, d: 10 * int(s1 == d), evidence=['S1', 'D']) cpd_u2 = FunctionCPD('U2', lambda s2, d: 2 * int(s2 == d), evidence=['S2', 'D']) cpd_d = DecisionDomain('D', [0, 1]) cid.add_cpds(cpd_d, cpd_s1, cpd_s2, cpd_u1, cpd_u2) return cid
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 random_cid(n_all: int, n_decisions: int, n_utilities: int, edge_density: float = 0.4, add_sr_edges: bool = True, add_cpds: bool = True, seed: int = None) -> CID: """Generates a random Cid with the specified number of nodes and edges""" all_names, decision_names, utility_names = get_node_names( n_all, n_decisions, n_utilities) edges = get_edges(all_names, utility_names, edge_density, seed=seed, allow_u_edges=False) cid = CID(edges, decision_names, utility_names) for uname in utility_names: for edge in edges: assert uname != edge[0] for i, d1 in enumerate(decision_names): for j, d2 in enumerate(decision_names[i + 1:]): assert d2 not in cid._get_ancestors_of(d1) if add_sr_edges: add_sufficient_recalls(cid) if add_cpds: for node in cid.nodes: if node in cid.all_decision_nodes: cid.add_cpds(DecisionDomain(node, [0, 1])) elif not cid.get_parents(node): # node is a root node cid.add_cpds(UniformRandomCPD(node, [0, 1])) else: cid.add_cpds( RandomlySampledFunctionCPD(node, cid.get_parents(node))) return cid
def get_introduced_bias() -> CID: cid = CID( [ ('A', 'X'), # defining the graph's nodes and edges ('Z', 'X'), ('Z', 'Y'), ('X', 'D'), ('X', 'Y'), ('D', 'U'), ('Y', 'U') ], decision_nodes=['D'], utility_nodes=['U']) cpd_a = UniformRandomCPD('A', [0, 1]) cpd_z = UniformRandomCPD('Z', [0, 1]) cpd_x = FunctionCPD('X', lambda a, z: a * z, evidence=['A', 'Z']) cpd_d = DecisionDomain('D', [0, 1]) cpd_y = FunctionCPD('Y', lambda x, z: x + z, evidence=['X', 'Z']) cpd_u = FunctionCPD('U', lambda d, y: -(d - y)**2, evidence=['D', 'Y']) cid.add_cpds(cpd_a, cpd_d, cpd_z, cpd_x, cpd_y, cpd_u) return cid
def basic2agent_3() -> MACID: macid = MACID( [ ('D1', 'D2'), # KM_NE should = {'D1': 1, 'D2': 0, 'D3': 1} ('D1', 'D3'), ('D2', 'D3'), ('D1', 'U1'), ('D1', 'U2'), ('D1', 'U3'), ('D2', 'U1'), ('D2', 'U2'), ('D2', 'U3'), ('D3', 'U1'), ('D3', 'U2'), ('D3', 'U3') ], { 0: { 'D': ['D1'], 'U': ['U1'] }, 1: { 'D': ['D2'], 'U': ['U2'] }, 2: { 'D': ['D3'], 'U': ['U3'] } }) cpd_d1 = DecisionDomain('D1', [0, 1]) cpd_d2 = DecisionDomain('D2', [0, 1]) cpd_d3 = DecisionDomain('D3', [0, 1]) cpd_u1 = TabularCPD('U1', 7, np.array([[0, 0, 0, 1, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]), evidence=['D1', 'D2', 'D3'], evidence_card=[2, 2, 2]) cpd_u2 = TabularCPD('U2', 7, np.array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 1, 0], [0, 1, 1, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]), evidence=['D1', 'D2', 'D3'], evidence_card=[2, 2, 2]) cpd_u3 = TabularCPD('U3', 7, np.array([[0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1, 0, 0]]), evidence=['D1', 'D2', 'D3'], evidence_card=[2, 2, 2]) macid.add_cpds(cpd_d1, cpd_d2, cpd_d3, cpd_u1, cpd_u2, cpd_u3) return macid
def get_minimal_cid() -> CID: cid = CID([('A', 'B')], decision_nodes=['A'], utility_nodes=['B']) cpd_a = DecisionDomain('A', [0, 1]) cpd_b = FunctionCPD('B', lambda a: a, evidence=['A']) cid.add_cpds(cpd_a, cpd_b) return cid