def compute_factors(probs, j_probs, tree):
    factors = np.zeros((probs.shape[0], 2, 2))
    root_id = tree.index(ROOT)
    features = np.arange(probs.shape[0]).tolist()
    features.remove(root_id)
    parents = tree.copy()
    parents.pop(root_id)
    factors[(root_id, 0, 0)] = factors[(root_id, 1, 0)] = probs[(root_id, 0)]
    factors[(root_id, 0, 1)] = factors[(root_id, 1, 1)] = probs[(root_id, 1)]
    factors[(features, 0, 0)] = (j_probs[(features, parents, 0, 0)] / probs[(parents, 0)])
    factors[(features, 1, 0)] = (j_probs[(features, parents, 0, 1)] / probs[(parents, 1)])
    factors[(features, 0, 1)] = (j_probs[(features, parents, 1, 0)] / probs[(parents, 0)])
    factors[(features, 1, 1)] = (j_probs[(features, parents, 1, 1)] / probs[(parents, 1)])
    return factors
def compute_factors(probs, j_probs, tree):
    factors = np.zeros((probs.shape[0], 2, 2))
    root_id = tree.index(ROOT)
    features = np.arange(probs.shape[0]).tolist()
    features.remove(root_id)
    parents = tree.copy()
    parents.pop(root_id)
    factors[(root_id, 0, 0)] = factors[(root_id, 1, 0)] = probs[(root_id, 0)]
    factors[(root_id, 0, 1)] = factors[(root_id, 1, 1)] = probs[(root_id, 1)]
    factors[(features, 0, 0)] = (j_probs[(features, parents, 0, 0)] / probs[(parents, 0)])
    factors[(features, 1, 0)] = (j_probs[(features, parents, 0, 1)] / probs[(parents, 1)])
    factors[(features, 0, 1)] = (j_probs[(features, parents, 1, 0)] / probs[(parents, 0)])
    factors[(features, 1, 1)] = (j_probs[(features, parents, 1, 1)] / probs[(parents, 1)])
    return factors