Example #1
0
def max_local(input: dit.Distribution,
              conditional: np.ndarray,
              eps: float = 0.01):
    rvs = input.get_rv_names()
    sorted_rvs = np.argsort([
        entropy(input.marginal([rv], rv_mode='indices').pmf)
        for rv in range(len(rvs))
    ])
    nudge_vectors = np.zeros(
        (input.outcome_length(), int(len(input) / 3), 3)
    )  # For each random variable we get (hopefully) a different nudge vector of len the input size
    max_impacts = np.zeros(input.outcome_length())
    for rv in sorted_rvs:
        nudge_vectors[rv, :, :], max_impacts[rv], _ = max_individual(
            input, conditional, eps / len(sorted_rvs), rv)
    return nudge_vectors, max_impacts
Example #2
0
def individual_nudge(old_X: dit.Distribution,
                     eps: float = 0.01,
                     rvs_other=None) -> dit.Distribution:
    mask = old_X._mask
    base = old_X.get_base()
    if old_X.outcome_length() == 1:
        return global_nudge(old_X, eps)
    outcomes = old_X.outcomes
    rv_names = old_X.get_rv_names()

    if rvs_other == None:
        rvs = old_X.get_rv_names()
        rvs_other = np.random.choice(rvs, len(rvs) - 1, replace=False)

    X_other, Xi_given_Xother = old_X.condition_on(rvs_other)
    nudge_size = len(Xi_given_Xother[0])

    if base == 'linear':
        nudge = generate_nudge(nudge_size, eps / len(Xi_given_Xother))
        for Xi in Xi_given_Xother:
            perform_nudge(Xi, nudge)
    else:
        nudge, sign = generate_log_nudge(nudge_size, eps)
        for Xi in Xi_given_Xother:
            perform_log_nudge(Xi, nudge, sign)
    new_X = dit.joint_from_factors(X_other, Xi_given_Xother).copy(base)
    #add back any missing outcomes
    dct = {o: new_X[o] if o in new_X.outcomes else 0.0 for o in outcomes}
    #print(outcomes, dct)
    new_X = dit.Distribution(dct)
    new_X.set_rv_names(rv_names)
    new_X.make_dense()
    new_X._mask = mask
    return new_X
Example #3
0
def max_individual_nudge(old_X: dit.Distribution,
                         YgivenX: np.ndarray,
                         eps: float = 0.01):
    if old_X.outcome_length() == 1:
        return max_global_nudge(old_X, YgivenX, eps)
    nudges, minimal_idx = max_nudge(old_X.copy('linear'),
                                    YgivenX,
                                    eps=eps,
                                    nudge_type='individual')
    # print("individual eps",sum([sum(abs(nudge)) for nudge in nudges]), eps, old_X.outcome_length())
    return do_max_individual_nudge(old_X, nudges, minimal_idx)
Example #4
0
def test_insert_join():
    """ Test insert_join """
    outcomes = ['00', '01', '10', '11']
    pmf = [1/4]*4
    d = Distribution(outcomes, pmf)
    assert_raises(IndexError, insert_join, d, 5, [[0], [1]])

    for idx in range(d.outcome_length()):
        d2 = insert_join(d, idx, [[0], [1]])
        m = d2.marginal([idx])
        npt.assert_allclose(d2.pmf, m.pmf)
Example #5
0
def test_insert_join():
    """ Test insert_join """
    outcomes = ['00', '01', '10', '11']
    pmf = [1 / 4] * 4
    d = Distribution(outcomes, pmf)
    with pytest.raises(IndexError):
        insert_join(d, 5, [[0], [1]])

    for idx in range(d.outcome_length()):
        d2 = insert_join(d, idx, [[0], [1]])
        m = d2.marginal([idx])
        assert np.allclose(d2.pmf, m.pmf)
Example #6
0
def max_local_nudge1(old_X: dit.Distribution,
                     YgivenX: np.ndarray,
                     eps: float = 0.01):
    if old_X.outcome_length() == 1:
        return max_global_nudge(old_X, YgivenX, eps)

    mask = old_X._mask
    base = old_X.get_base()
    new_X = old_X.copy(base=base)
    old_X.make_dense()
    outcomes = old_X.outcomes
    rvs = old_X.get_rv_names()

    individual_nudges, _ = max_nudge(old_X.copy('linear'),
                                     YgivenX,
                                     eps=eps,
                                     nudge_type='local')
    new_Xs = np.zeros((old_X.outcome_length(), len(old_X)))
    for i, nudges in enumerate(individual_nudges):
        tmp = do_max_individual_nudge(old_X, nudges, i)

        # print(i, tmp.pmf, old_X.pmf, new_Xs)
        new_Xs[i, :] = tmp.pmf - old_X.pmf

    nudge = new_Xs.sum(axis=0)
    nudge = eps * nudge / (abs(nudge).sum())

    if base == 'linear':
        perform_nudge(new_X, nudge)
    else:
        log_nudge, sign = np.log(np.abs(nudge)), np.sign(nudge)
        perform_log_nudge(new_X, log_nudge, sign)
    dct = {o: new_X[o] if o in new_X.outcomes else 0.0 for o in outcomes}
    #print(outcomes, dct)
    new_X = dit.Distribution(dct)
    new_X.set_rv_names(rvs)
    new_X._mask = mask
    return new_X
Example #7
0
def do_derkjanistic_nudge(input_dist: dit.Distribution,  nudge_size:float):
    "Unoptimized derkjanistic nudge"
    rvs = input_dist.outcome_length()
    alphabet = input_dist.alphabet[0]
    new_distribution = input_dist.pmf
    for _ in range(len(new_distribution)):
        state_vectors = np.tile(np.random.choice(alphabet, rvs, replace=True), (4, 1))
        x_i, x_j = np.random.choice(rvs, 2, replace=False)
        states_i = np.random.choice(alphabet, 2, replace=False)
        states_j = np.random.choice(alphabet, 2, replace=False)
        for i in range(2):
            for j in range(2):
                state_vectors[i * 2 + j, [x_i, x_j]] = states_i[i], states_j[j]
        state_strings = sorted([tuple(vector) for vector in state_vectors])
        #print(input_dist.outcomes)
        state_indices = [i for i, sample in enumerate(input_dist.sample_space()) if sample in state_strings]
        selected_states =  [{'label': label, 'index': index, 'prob': input_dist[label]} for label, index in
                zip(state_strings, state_indices)]
        random.shuffle(selected_states)
        #print(selected_states)
        if np.random.random() > 0.5:
            negs = (selected_states[0], selected_states[3])
            poss = (selected_states[1], selected_states[2])
        else:
            negs = (selected_states[1], selected_states[2])
            poss = (selected_states[0], selected_states[3])

        this_mutation_size = min(input_dist[negs[0]['label']],
                                 input_dist[negs[1]['label']],
                                 1-input_dist[poss[0]['label']],
                                 1-input_dist[poss[1]['label']],
                                 nudge_size)
        this_mutation_size = np.random.uniform(0, this_mutation_size)
        for neg in negs:
            new_distribution[neg['index']] -= this_mutation_size
        for pos in poss:
            new_distribution[pos['index']] += this_mutation_size
        if np.any(new_distribution < 0):
            print("something went wrong")
            print("negative states {}".format(negs))
            print("positive_states {}".format(poss))
            print("the mutation size {}".format(this_mutation_size))
            print("the negative probs {}, {}".format(new_distribution[negs[0]["index"]],
                                                     new_distribution[negs[1]["index"]]))
            print("the positive probs {}, {}".format(new_distribution[poss[0]["index"]],
                                                     new_distribution[poss[1]["index"]]))
            print(new_distribution)
            raise ValueError()
    return new_distribution
Example #8
0
def max_local_nudge2(old_X: dit.Distribution,
                     YgivenX: np.ndarray,
                     eps: float = 0.01):
    if old_X.outcome_length() == 1:
        return max_global_nudge(old_X, YgivenX, eps)

    mask = old_X._mask
    base = old_X.get_base()
    new_X = old_X.copy(base=base)
    old_X.make_dense()
    rvs = old_X.get_rv_names()
    sorted_rvs = np.argsort([
        entropy(old_X.marginal([rv], rv_mode='indices').pmf)
        for rv in range(len(rvs))
    ])
    oldshape = len(old_X)
    outcomes = old_X.outcomes
    # print("before", new_X.pmf.shape)
    for i, rv in enumerate(sorted_rvs):
        nudges, _ = max_nudge(new_X.copy('linear'),
                              YgivenX,
                              eps=(eps / len(sorted_rvs)),
                              nudge_type='individual',
                              minimal_entropy_idx=rv)
        #        print("local eps",sum([sum(abs(nudge)) for nudge in nudges]), eps, old_X.outcome_length())
        new_X = do_max_individual_nudge(new_X, nudges, rv, True)
        # print("after {}".format(i), new_X.pmf.shape)
        new_X.make_dense()
        newshape = len(new_X)
    #  if oldshape != newshape:
    #      print(nudges)
    #   print("after {} and making dense".format(i), new_X.pmf.shape)
    dct = {o: new_X[o] if o in new_X.outcomes else 0.0 for o in outcomes}
    #print(outcomes, dct)
    new_X = dit.Distribution(dct)
    new_X.set_rv_names(rvs)
    new_X._mask = mask
    return new_X