def max_individual(input: dit.Distribution, conditional: np.ndarray, eps: float = 0.01, minimal_entropy_idx=None): rvs = input.get_rv_names() conditional = conditional / conditional.sum() states = len(input.alphabet[0]) if not minimal_entropy_idx == 0 and not minimal_entropy_idx: minimal_entropy_idx = np.argmin([ entropy(input.marginal([rv], rv_mode='indices').pmf) for rv in range(len(rvs)) ]) non_minimal_rvs = rvs[:minimal_entropy_idx] + rvs[minimal_entropy_idx + 1:] non_minimal_marginal, minimal_conditional = input.condition_on( non_minimal_rvs) [d.make_dense() for d in minimal_conditional] # minimal_conditional = np.stack([d.pmf for d in minimal_conditional]) # print("minimal_conditional:",minimal_conditional) indiv_shape = (len(minimal_conditional), len(minimal_conditional[0])) # minimal_conditional = minimal_conditional.flatten() nudge_vector = np.zeros(indiv_shape) rotated_conditional = R(conditional, minimal_entropy_idx, len(rvs), states) total_max_impact = 0 # print(len(rvs), (eps / 2)/len(minimal_conditional)) for i, mc_dist in enumerate(minimal_conditional): rows = rotated_conditional[i * states:(i + 1) * states, :] max_impact = 0 for allignment in itertools.product( [-1, 1], repeat=rotated_conditional.shape[1]): allignment = np.array(allignment) if np.all(allignment == 1) or np.all(allignment == -1): continue scores = np.sum(allignment * rows, axis=1) # Add rotation of scores so that scores are well aligned. # Weigh scores using the non_minimal_marginal vector, impact = find_max_impact(scores, mc_dist.pmf, (eps / 2) / len(minimal_conditional)) if impact > max_impact: nudge_vector[i, :] = vector max_impact = impact total_max_impact += max_impact return nudge_vector, total_max_impact, minimal_entropy_idx
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
def test_to_string8(): outcomes = ['00', '01', '10', '11'] pmf = [1/4]*4 d = Distribution(outcomes, pmf) d = d.marginal([0]) s = d.to_string(show_mask='!') s_ = """Class: Distribution Alphabet: ('0', '1') for all rvs Base: linear Outcome Class: str Outcome Length: 1 (mask: 2) RV Names: None x p(x) 0! 0.5 1! 0.5""" assert_equal(s, s_)
def test_to_string8(): outcomes = ['00', '01', '10', '11'] pmf = [1/4]*4 d = Distribution(outcomes, pmf) d = d.marginal([0]) s = d.to_string(show_mask='!') s_ = """Class: Distribution Alphabet: ('0', '1') for all rvs Base: linear Outcome Class: str Outcome Length: 1 (mask: 2) RV Names: None x p(x) 0! 0.5 1! 0.5""" assert s == s_
def test_to_string4(): # Basic with marginal outcomes = ['00', '01', '10', '11'] pmf = [1/4]*4 d = Distribution(outcomes, pmf) d = d.marginal([0]) s = d.to_string() s_ = """Class: Distribution Alphabet: ('0', '1') for all rvs Base: linear Outcome Class: str Outcome Length: 1 RV Names: None x p(x) 0 0.5 1 0.5""" assert_equal(s, s_)
def test_to_string4(): # Basic with marginal outcomes = ['00', '01', '10', '11'] pmf = [1/4]*4 d = Distribution(outcomes, pmf) d = d.marginal([0]) s = d.to_string() s_ = """Class: Distribution Alphabet: ('0', '1') for all rvs Base: linear Outcome Class: str Outcome Length: 1 RV Names: None x p(x) 0 0.5 1 0.5""" assert s == s_
def test_to_string5(): # Basic with marginal and mask outcomes = ['00', '01', '10', '11'] pmf = [1 / 4] * 4 d = Distribution(outcomes, pmf) d = d.marginal([0]) s = d.to_string(show_mask=True) s_ = """Class: Distribution Alphabet: ('0', '1') for all rvs Base: linear Outcome Class: str Outcome Length: 1 (mask: 2) RV Names: None x p(x) 0* 0.5 1* 0.5""" assert_equal(s, s_)
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