def attractors(net, size=None, encode=True): if not is_network(net): raise TypeError("net must be a network or a networkx DiGraph") elif is_fixed_sized(net) and size is not None: raise ValueError("fixed sized networks require size is None") elif not is_fixed_sized(net) and size is None: raise ValueError("variable sized networks require a size") if size is None: g = net.to_networkx_graph() encoder = net.state_space()._unsafe_encode else: g = net.to_networkx_graph(size) encoder = net.state_space(size)._unsafe_encode modules = list(nx.strongly_connected_components(g)) dag = nx.condensation(g) dag_list = list(nx.topological_sort(dag)) attractors = {} for module_number in dag_list: parents = greatest_predecessors(dag, module_number) if len(parents) == 0: nodes = modules[module_number] attractors[module_number] = { 'eff_module': nodes, 'attractors': attractors_brute_force(net, size, subgraph=nodes) } else: parent_modules = [attractors[p]['eff_module'] for p in parents] parent_attractors = [attractors[p]['attractors'] for p in parents] parent = direct_sum(parent_modules, parent_attractors) subgraph = modules[module_number] attractors[module_number] = { 'eff_module': parent[0] | subgraph, 'attractors': attractors_brute_force(net, size, subgraph=subgraph, parent=parent) } outputs = list( filter(lambda m: len(list(dag.successors(m))) == 0, dag_list)) parent_modules = [attractors[o]['eff_module'] for o in outputs] parent_attractors = [attractors[o]['attractors'] for o in outputs] _, attractors = direct_sum(parent_modules, parent_attractors) if encode: return list( map(lambda attractor: list(map(encoder, attractor)), attractors)) else: return attractors
def test_is_fixed_sized(self): """ Ensure that RewiredECA is of fixed size """ from neet.interfaces import is_fixed_sized self.assertTrue(is_fixed_sized(RewiredECA)) self.assertTrue(is_fixed_sized(RewiredECA(23, size=3))) self.assertTrue(is_fixed_sized(RewiredECA( 30, wiring=[[-1, 0, 1], [0, 1, 2], [1, 2, 3]])))
def attractors_brute_force(net, size=None, subgraph=None, parent=None, encode=False): if not is_network(net): raise TypeError("net must be a network or a networkx DiGraph") elif is_fixed_sized(net) and size is not None: raise ValueError("fixed sized networks require size is None") elif not is_fixed_sized(net) and size is None: raise ValueError("variable sized networks require a size") if size is None: decoder = net.state_space().decode else: decoder = net.state_space(size).decode mapping, trans = transitions(net, size=size, subgraph=subgraph, parent=parent) collapsed = [None] * len(trans) for s, t in trans: try: collapsed[s] = t except IndexError: raise assert (all(map(lambda x: x is not None, collapsed))) cycles = attrs(collapsed) if mapping is None: if encode: attractors = cycles else: attractors = [] for attr in cycles: attractors.append(list(map(decoder, attr))) elif encode: attractors = [] for attr in cycles: attractors.append(list(map(lambda state: mapping[state], attr))) else: attractors = [] for attr in cycles: attractors.append( list(map(lambda state: decoder(mapping[state]), attr))) return attractors
def transitions(net, size=None, subgraph=None, parent=None): if not is_network(net): raise TypeError("net is not a network") if is_fixed_sized(net): if size is not None: raise ValueError("size must be None for fixed sized networks") size = net.size state_space = net.state_space() else: if size is None: raise ValueError( "size must not be None for variable sized networks") state_space = net.state_space(size) encoder = state_space._unsafe_encode if subgraph is None: backward = None trans = [None] * state_space.volume for i, state in enumerate(state_space): net._unsafe_update(state) trans[i] = (i, encoder(state)) else: if parent is None: pin = [n for n in range(state_space.ndim) if n not in subgraph] trans = [None] * 2**len(subgraph) space = subspace(subgraph, size) else: parent_nodes, parent_attractors = parent pin = [ n for n in range(state_space.ndim) if n not in (subgraph | parent_nodes) ] trans = [None ] * (sum(map(len, parent_attractors)) * 2**len(subgraph)) space = subspace(subgraph, size, dynamic_values=parent) forward = {} backward = {} k = 0 for i, state in enumerate(space): source = encoder(state) net._unsafe_update(state, pin=pin) target = encoder(state) if source not in forward: forward[source] = k backward[k] = source k += 1 if target not in forward: forward[target] = k backward[k] = target k += 1 trans[i] = (forward[source], forward[target]) return backward, trans
def test_is_fixed_sized(self): net = self.IsNetwork() self.assertFalse(is_fixed_sized(net)) self.assertFalse(is_fixed_sized(type(net))) not_net = self.IsNotNetwork() self.assertFalse(is_fixed_sized(not_net)) self.assertFalse(is_fixed_sized(type(not_net))) net = self.FixedSizeNetwork() self.assertTrue(is_fixed_sized(net)) self.assertTrue(is_fixed_sized(type(net))) not_net = self.NotFixedSizedNetwork() self.assertFalse(is_fixed_sized(not_net)) self.assertFalse(is_fixed_sized(type(not_net)))
def test_is_fixed_sized(self): from neet.interfaces import is_fixed_sized self.assertTrue(is_fixed_sized(bnet.WTNetwork)) self.assertTrue(is_fixed_sized(bnet.WTNetwork([[1]])))
def test_is_not_fixed_sized(self): from neet.interfaces import is_fixed_sized self.assertFalse(is_fixed_sized(ca.ECA)) self.assertFalse(is_fixed_sized(ca.ECA(23)))
def test_is_fixed_sized(self): from neet.interfaces import is_fixed_sized self.assertTrue(is_fixed_sized(LogicNetwork([([0], {'0'})])))