Ejemplo n.º 1
0
def voi(cid: CID, decision: str, variable: str) -> float:
    # TODO test this method
    new = cid.copy()
    new.add_edge(variable, decision)
    new.impute_optimal_policy()
    ev1: float = new.expected_utility({})
    new = cid.copy()
    new.remove_edge(variable, decision)
    new.impute_optimal_policy()
    ev2: float = new.expected_utility({})
    return ev1 - ev2
Ejemplo n.º 2
0
def _add_sufficient_recall(cid: CID, dec1: str, dec2: str,
                           utility_node: str) -> None:
    """Add edges to a cid until `dec2` has sufficient recall of `dec1` (to optimize utility)

    this is done by adding edges from non-collider nodes until recall is adequate
    """

    if dec2 in cid._get_ancestors_of(dec1):
        raise ValueError('{} is an ancestor of {}'.format(dec2, dec1))

    cid2 = cid.copy()
    cid2.add_edge('pi', dec1)

    while cid2.is_active_trail('pi',
                               utility_node,
                               observed=cid.get_parents(dec2) + [dec2]):
        path = find_active_path(cid2, 'pi', utility_node,
                                cid.get_parents(dec2) + [dec2])
        if path is None:
            raise Exception(
                "couldn't find path even though there should be an active trail"
            )
        while True:
            i = random.randrange(1, len(path) - 1)
            # print('consider {}--{}--{}'.format(path[i-1], path[i], path[i+1]),end='')
            collider = ((path[i - 1], path[i]) in cid2.edges) and (
                (path[i + 1], path[i]) in cid2.edges)
            if not collider:
                if dec2 not in cid2._get_ancestors_of(path[i]):
                    # print('add {}->{}'.format(path[i], dec2), end=' ')
                    cid.add_edge(path[i], dec2)
                    cid2.add_edge(path[i], dec2)
                    break