Esempio n. 1
0
 def test_get_motif(macid_basic_subgames: MACID) -> None:
     assert get_motif(macid_basic_subgames,
                      ["D3", "D2", "U2", "D11", "D12", "U3"],
                      0) == "backward"
     assert get_motif(macid_basic_subgames,
                      ["D3", "D2", "U2", "D11", "D12", "U3"], 1) == "fork"
     assert get_motif(macid_basic_subgames,
                      ["D3", "D2", "U2", "D11", "D12", "U3"],
                      2) == "collider"
     assert get_motif(macid_basic_subgames,
                      ["D3", "D2", "U2", "D11", "D12", "U3"],
                      4) == "forward"
     assert get_motif(macid_basic_subgames,
                      ["D3", "D2", "U2", "D11", "D12", "U3"],
                      5) == "endpoint"
Esempio n. 2
0
def _add_sufficient_recall(mb: MACIDBase, d1: str, d2: str,
                           utility_node: str) -> None:
    """Add edges to a (MA)CID until an agent at `d2` has sufficient recall of `d1` to optimise utility_node.

    d1, d2 and utility node all belong to the same agent.

    `d2' has sufficient recall of `d1' if d2 does not strategically rely on d1. This means
    that d1 is not s-reachable from d2.

    edges are added from non-collider nodes along an active path from the mechanism of `d1' to
    somue utilty node descended from d2 until recall is sufficient.
    """

    if d2 in mb._get_ancestors_of(d1):
        raise ValueError("{} is an ancestor of {}".format(d2, d1))

    mg = MechanismGraph(mb)
    while mg.is_active_trail(d1 + "mec",
                             utility_node,
                             observed=mg.get_parents(d2) + [d2]):
        path = find_active_path(mg, d1 + "mec", utility_node,
                                {d2, *mg.get_parents(d2)})
        if path is None:
            raise RuntimeError(
                "couldn't find path even though there should be an active trail"
            )
        while True:
            idx = random.randrange(1, len(path) - 1)
            if get_motif(mg, path, idx) != "collider":
                if d2 not in mg._get_ancestors_of(
                        path[idx]):  # to prevent cycles
                    mb.add_edge(path[idx], d2)
                    mg.add_edge(path[idx], d2)
                    break
Esempio n. 3
0
 def test_invalid_target(macid_basic_subgames: MACID) -> None:
     with pytest.raises(KeyError):
         get_motif(macid_basic_subgames,
                   ["D3", "_", "U2", "D11", "D12", "U3"], 5)
Esempio n. 4
0
 def test_invalid_index(macid_basic_subgames: MACID) -> None:
     with pytest.raises(IndexError):
         get_motif(macid_basic_subgames,
                   ["D3", "D2", "U2", "D11", "D12", "U3"], 6)