def test_cut_mechanisms(macro_subsystem, propagation_delay): cut = models.Cut((0,), (1, 2, 3)) assert list(macro_subsystem.apply_cut(cut).cut_mechanisms) == [(0,), (0, 1)] cut = models.Cut((1, 3), (0, 2, 4, 5, 6, 7)) assert list(propagation_delay.apply_cut(cut).cut_mechanisms) == [ (1,), (2,), (0, 1), (0, 2), (1, 2), (0, 1, 2)]
def test_json_deserialization(s, transition): objects = [ Direction.CAUSE, s.network, # Network s, # Subsystem models.Bipartition(models.Part((0, ), ()), models.Part((1, ), (2, 3))), models.KPartition(models.Part((0, ), ()), models.Part((1, ), (2, 3))), models.Tripartition(models.Part((0, ), ()), models.Part((1, ), (2, 3)), models.Part((3, ), (4, ))), models.Cut((0, ), (2, )), models.NullCut((0, 1)), models.KCut( Direction.CAUSE, models.KPartition(models.Part((0, ), ()), models.Part((1, ), (2, 3)))), s.concept((1, 2)), s.concept((1, )), compute.ces(s), compute.sia(s), transition, transition.find_actual_cause((0, ), (0, )), actual.account(transition), actual.sia(transition) ] for o in objects: loaded = jsonify.loads(jsonify.dumps(o)) assert loaded == o
def test_macro_cut_is_for_micro_indices(s): with pytest.raises(ValueError): macro.MacroSubsystem(s.network, s.state, s.node_indices, blackbox=macro.Blackbox((2, ), (0, 1)), cut=models.Cut((0, ), (1, )))
def test_inherited_cache_must_come_from_uncut_subsystem(redis_cache): s = examples.basic_subsystem() cut_s = Subsystem(s.network, s.state, s.node_indices, cut=models.Cut((0, 2), (1, ))) with pytest.raises(ValueError): cache.MICECache(s, cut_s._mice_cache)
def test_cuts_can_have_node_labels(node_labels): models.NullCut((0, 1), node_labels=node_labels) models.Cut((0, ), (1, ), node_labels=node_labels) k_partition = models.KPartition(models.Part((0, 1), (0, )), models.Part((), (1, )), node_labels=node_labels) models.KCut(Direction.CAUSE, k_partition, node_labels=node_labels)
def test_only_cache_uncut_subsystem_mices(redis_cache, flush_redis, s): s = Subsystem(s.network, (1, 0, 0), s.node_indices, cut=models.Cut((1, ), (0, 2))) mechanism = (1, ) # has a core cause s.find_mice('past', mechanism) # don't cache anything because subsystem is cut assert s._mice_cache.size() == 0
def test_xor_propogation_delay(): # Three interconnected XOR gates, with COPY gates along each connection # acting as propagation delays. nodes = 9 tpm = np.zeros((2**nodes, nodes)) for psi, ps in enumerate(utils.all_states(nodes)): cs = [0 for i in range(nodes)] if ps[2] ^ ps[7]: cs[0] = 1 if ps[0] == 1: cs[1] = 1 cs[8] = 1 if ps[1] ^ ps[5]: cs[3] = 1 if ps[3] == 1: cs[2] = 1 cs[4] = 1 if ps[4] ^ ps[8]: cs[6] = 1 if ps[6] == 1: cs[5] = 1 cs[7] = 1 tpm[psi, :] = cs cm = np.array([[0, 1, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0]]) # The state of the system is all OFF state = (0, 0, 0, 0, 0, 0, 0, 0, 0) network = Network(tpm, cm=cm) partition = ((0, 2, 7), (1, 3, 5), (4, 6, 8)) output_indices = (0, 3, 6) blackbox = macro.Blackbox(partition, output_indices) assert blackbox.hidden_indices == (1, 2, 4, 5, 7, 8) time = 2 subsys = macro.MacroSubsystem(network, state, network.node_indices, blackbox=blackbox, time_scale=time) sia = compute.sia(subsys) assert sia.phi == 1.874999 assert sia.cut == models.Cut((0, ), (1, 2, 3, 4, 5, 6, 7, 8))
def test_cut_matrix(): cut = models.Cut((), (0, )) matrix = np.array([[0]]) assert np.array_equal(cut.cut_matrix(1), matrix) cut = models.Cut((0, ), (1, )) matrix = np.array([ [0, 1], [0, 0], ]) assert np.array_equal(cut.cut_matrix(2), matrix) cut = models.Cut((0, 2), (1, 2)) matrix = np.array([ [0, 1, 1], [0, 0, 0], [0, 1, 1], ]) assert np.array_equal(cut.cut_matrix(3), matrix) cut = models.Cut((), ()) assert np.array_equal(cut.cut_matrix(0), np.ndarray(shape=(0, 0)))
def test_cut_matrix(): cut = models.Cut((), (0,)) matrix = np.array([[0]]) assert np.array_equal(cut.cut_matrix(), matrix) cut = models.Cut((0,), (1,)) matrix = np.array([ [0, 1], [0, 0], ]) assert np.array_equal(cut.cut_matrix(), matrix) cut = models.Cut((0, 2), (1, 2)) matrix = np.array([ [0, 1, 1], [0, 0, 0], [0, 1, 1], ]) assert np.array_equal(cut.cut_matrix(), matrix) cut = models.Cut((), ()) assert np.array_equal(cut.cut_matrix(), np.array([]))
def test_damaged(s): # Build cut subsystem from s cut = models.Cut((0, ), (1, 2)) cut_s = Subsystem(s.network, s.state, s.node_indices, cut=cut) # Cut splits mechanism: m1 = mice(mechanism=(0, 1), purview=(1, 2), direction=Direction.EFFECT) assert m1.damaged_by_cut(cut_s) assert not m1.damaged_by_cut(s) # Cut splits mechanism & purview (but not *only* mechanism) m2 = mice(mechanism=(0, ), purview=(1, 2), direction=Direction.EFFECT) assert m2.damaged_by_cut(cut_s) assert not m2.damaged_by_cut(s)
def test_apply_cut(): cm = np.array([ [1, 0, 1, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 1, 0] ]) cut = models.Cut(from_nodes=(0, 3), to_nodes=(1, 2)) cut_cm = np.array([ [1, 0, 0, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 0, 0] ]) assert np.array_equal(cut.apply_cut(cm), cut_cm)
def test_damaged(s): # Build cut subsystem from s cut = models.Cut((0,), (1, 2)) subsys = Subsystem(s.network, s.state, s.node_indices, cut=cut) # Cut splits mechanism: mip = mock.MagicMock(mechanism=(0, 1), purview=(1, 2), direction='future') mice = models.Mice(mip) assert mice.damaged_by_cut(subsys) assert not mice.damaged_by_cut(s) # Cut splits mechanism & purview (but not *only* mechanism) mip = mock.MagicMock(mechanism=(0,), purview=(1, 2), direction='future') mice = models.Mice(mip) assert mice.damaged_by_cut(subsys) assert not mice.damaged_by_cut(s)
def test_cut_relevant_connections_mice_is_not_reusable(redis_cache): """If relevant connections are cut, cached mice are not usable when a cache is built from a parent cache.""" s = examples.basic_subsystem() mechanism = (1, ) mice = s.find_mice(Direction.CAUSE, mechanism) assert s._mice_cache.size() == 1 # cached assert mice.purview == (2, ) # Cuts connections from 2 -> 1 cut = models.Cut((0, 2), (1, )) cut_s = Subsystem(s.network, s.state, s.node_indices, cut=cut, mice_cache=s._mice_cache) key = cut_s._mice_cache.key(Direction.CAUSE, mechanism) assert cut_s._mice_cache.get(key) is None
def test_split_mechanism_mice_is_not_reusable(redis_cache, flush_redis): """If mechanism is split, then cached mice are not usable when a cache is built from a parent cache.""" s = examples.basic_subsystem() mechanism = (0, 1) mice = s.find_mice('past', mechanism) assert s._mice_cache.size() == 1 # cached assert mice.purview == (1, 2) # Splits mechanism, but not relevant connections: cut = models.Cut((0, ), (1, 2)) cut_s = Subsystem(s.network, s.state, s.node_indices, cut=cut, mice_cache=s._mice_cache) key = cut_s._mice_cache.key('past', mechanism) assert cut_s._mice_cache.get(key) is None
def test_inherited_mice_cache_keeps_unaffected_mice(redis_cache, flush_redis): """Cached Mice are saved from the parent cache if both the mechanism and the relevant connections are not cut.""" s = examples.basic_subsystem() mechanism = (1, ) mice = s.find_mice('past', mechanism) assert s._mice_cache.size() == 1 # cached assert mice.purview == (2, ) # Does not cut from 0 -> 1 or split mechanism cut = models.Cut((0, 1), (2, )) cut_s = Subsystem(s.network, s.state, s.node_indices, cut=cut, mice_cache=s._mice_cache) key = cut_s._mice_cache.key('past', mechanism) assert cut_s._mice_cache.get(key) == mice
def test_apply_cut(): # fmt: off cm = np.array([ [1, 0, 1, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 1, 0], ]) # fmt: on cut = models.Cut(from_nodes=(0, 3), to_nodes=(1, 2)) # fmt: off cut_cm = np.array([ [1, 0, 0, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 0, 0], ]) # fmt: on assert np.array_equal(cut.apply_cut(cm), cut_cm)
def test_sia_bipartitions(): with config.override(CUT_ONE_APPROXIMATION=False): answer = [models.Cut((1,), (2, 3, 4)), models.Cut((2,), (1, 3, 4)), models.Cut((1, 2), (3, 4)), models.Cut((3,), (1, 2, 4)), models.Cut((1, 3), (2, 4)), models.Cut((2, 3), (1, 4)), models.Cut((1, 2, 3), (4,)), models.Cut((4,), (1, 2, 3)), models.Cut((1, 4), (2, 3)), models.Cut((2, 4), (1, 3)), models.Cut((1, 2, 4), (3,)), models.Cut((3, 4), (1, 2)), models.Cut((1, 3, 4), (2,)), models.Cut((2, 3, 4), (1,))] assert sia_bipartitions((1, 2, 3, 4)) == answer with config.override(CUT_ONE_APPROXIMATION=True): answer = [models.Cut((1,), (2, 3, 4)), models.Cut((2,), (1, 3, 4)), models.Cut((3,), (1, 2, 4)), models.Cut((4,), (1, 2, 3)), models.Cut((2, 3, 4), (1,)), models.Cut((1, 3, 4), (2,)), models.Cut((1, 2, 4), (3,)), models.Cut((1, 2, 3), (4,))] assert sia_bipartitions((1, 2, 3, 4)) == answer
# TODO: split these into `concept` and `big_phi` tests # Answers # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ standard_answer = { 'phi': 2.3125, 'unpartitioned_small_phis': { (1,): 0.25, (2,): 0.5, (0, 1): 0.333333, (0, 1, 2): 0.5 }, 'len_partitioned_ces': 1, 'sum_partitioned_small_phis': 0.5, 'cut': models.Cut(from_nodes=(1, 2), to_nodes=(0,)) } noised_answer = { 'phi': 1.928592, 'unpartitioned_small_phis': { (0,): 0.0625, (1,): 0.2, (2,): 0.316326, (0, 1): 0.319047, (0, 2): 0.0125, (1, 2): 0.263847, (0, 1, 2): 0.35 }, 'len_partitioned_ces': 7,
def test_cut_equality(): cut1 = models.Cut((0, ), (1, )) cut2 = models.Cut((0, ), (1, )) assert cut1 == cut2 assert hash(cut1) == hash(cut2)
def test_cut_splits_connections(): cut = models.Cut((0, 3), (1, 2)) assert cut.cuts_connections((0, ), (1, 2)) assert cut.cuts_connections((0, 3), (1, )) assert not cut.cuts_connections((1, 2), (0, )) assert not cut.cuts_connections((1, ), (0, 3))
def test_cut_all_cut_mechanisms(): cut = models.Cut((0,), (1, 2)) assert cut.all_cut_mechanisms((0, 1, 2)) == ((0, 1), (0, 2), (0, 1, 2)) assert cut.all_cut_mechanisms((0, 1)) == ((0, 1),)
def test_cut_splits_mechanism(): cut = models.Cut((0,), (1, 2)) assert cut.splits_mechanism((0, 1)) assert not cut.splits_mechanism((0,)) assert not cut.splits_mechanism((1, 2))
def test_basic_nor_or(): # A system composed of NOR and OR (copy) gates, which mimics the basic # pyphi network nodes = 12 tpm = np.zeros((2**nodes, nodes)) for psi, ps in enumerate(utils.all_states(nodes)): cs = [0 for i in range(nodes)] if ps[5] == 0 and ps[11] == 0: cs[0] = 1 if ps[0] == 0: cs[1] = 1 if ps[1] == 1: cs[2] = 1 if ps[11] == 0: cs[3] = 1 if ps[3] == 0: cs[4] = 1 if ps[4] == 1: cs[5] = 1 if ps[2] == 0: cs[6] = 1 if ps[5] == 0: cs[7] = 1 if ps[6] == 0 and ps[7] == 0: cs[8] = 1 if ps[2] == 0 and ps[5] == 0: cs[9] = 1 if ps[9] == 1: cs[10] = 1 if ps[8] == 0 and ps[10] == 0: cs[11] = 1 tpm[psi, :] = cs cm = np.array([ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], ]) state = (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0) network = Network(tpm, cm=cm) # (0, 1, 2) compose the OR element, # (3, 4, 5) the COPY, # (6, 7, 8, 9, 10, 11) the XOR partition = ((0, 1, 2), (3, 4, 5), (6, 7, 8, 9, 10, 11)) output = (2, 5, 11) blackbox = macro.Blackbox(partition, output) assert blackbox.hidden_indices == (0, 1, 3, 4, 6, 7, 8, 9, 10) time = 3 sub = macro.MacroSubsystem(network, state, network.node_indices, blackbox=blackbox, time_scale=time) with config.override(CUT_ONE_APPROXIMATION=True): sia = compute.sia(sub) assert sia.phi == 1.958332 assert sia.cut == models.Cut((6, ), (0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11))
def test_apply_cut(): cm = np.array([[1, 0, 1, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 1, 0]]) cut = models.Cut(severed=(0, 3), intact=(1, 2)) cut_cm = np.array([[1, 0, 0, 0], [1, 1, 1, 1], [0, 1, 0, 1], [1, 0, 0, 0]]) assert np.array_equal(utils.apply_cut(cut, cm), cut_cm)
def test_cut_all_cut_mechanisms(): cut = models.Cut((0, ), (1, 2)) assert list(cut.all_cut_mechanisms()) == [(0, 1), (0, 2), (0, 1, 2)] cut = models.Cut((1, ), (5, )) assert list(cut.all_cut_mechanisms()) == [(1, 5)]
def test_cut_is_null(): cut = models.Cut((0, ), (1, 2)) assert not cut.is_null
def test_cut_indices(): cut = models.Cut((0, ), (1, 2)) assert cut.indices == (0, 1, 2) cut = models.Cut((7, ), (3, 1)) assert cut.indices == (1, 3, 7)
# Answers # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ standard_answer = { 'phi': 2.312497, 'unpartitioned_small_phis': { (1,): 0.25, (2,): 0.5, (0, 1): 0.333333, (0, 1, 2): 0.5 }, 'len_partitioned_constellation': 1, 'sum_partitioned_small_phis': 0.5, 'cut': models.Cut(severed=(1, 2), intact=(0,)) } noised_answer = { 'phi': 1.928594, 'unpartitioned_small_phis': { (0,): 0.0625, (1,): 0.2, (2,): 0.316326, (0, 1): 0.319047, (0, 2): 0.0125, (1, 2): 0.263847, (0, 1, 2): 0.35 }, 'len_partitioned_constellation': 7,