def gen_unique_cms(num_nodes): cms = product(*[[0,1]]*(num_nodes**2)) # Warning: mind-numbingly inefficient (brute force), don't use a lot of nodes (like, more than 4 sounds scary but I haven't tried it) unique_cms = set() #there will be 104 unique cms at 3 nodes with recurrent loops # look at all cms, add uniques to unique_cms for cm in cms: np_cm = np.array(cm) np_cm.shape = (num_nodes, num_nodes) unique_cms.add(tuple([tuple(x) for x in normalize_cm(np_cm)])) return unique_cms
def main(): # Size of Network ####################################################### NUM_NODES = 3 # Useful Constants ####################################################### unique_cms = gen_unique_cms(NUM_NODES) all_activations = [p for p in product([0,1], repeat=NUM_NODES)] # all possible activation states past_state = [0 for _ in range(NUM_NODES)] # Greater-Than mechanisms G1 = G(1) G2 = G(2) G3 = G(3) # motifs from the paper "Motifs in the Brain", same ordering motifs_mapping = [ [[0,0,0], [1,0,0], [1,0,0]], [[0,0,0], [1,0,0], [0,1,0]], [[0,0,0], [1,0,1], [0,0,0]], [[0,1,0], [1,0,0], [1,0,0]], [[0,0,0], [1,0,0], [1,1,0]], [[0,1,1], [1,0,0], [0,0,0]], [[0,0,1], [1,0,0], [0,1,0]], [[0,1,0], [1,0,0], [1,1,0]], [[0,1,1], [1,0,0], [1,0,0]], [[0,1,0], [1,0,1], [1,0,0]], [[0,0,0], [1,0,1], [1,1,0]], [[0,1,1], [1,0,0], [1,1,0]], [[0,1,1], [1,0,1], [1,1,0]], ] # all nodes have self loop motifs_plus_self_mapping = [ [[1,0,0], [1,1,0], [1,0,1]], [[1,0,0], [1,1,0], [0,1,1]], [[1,0,0], [1,1,1], [0,0,1]], [[1,1,0], [1,1,0], [1,0,1]], [[1,0,0], [1,1,0], [1,1,1]], [[1,1,1], [1,1,0], [0,0,1]], [[1,0,1], [1,1,0], [0,1,1]], [[1,1,0], [1,1,0], [1,1,1]], [[1,1,1], [1,1,0], [1,0,1]], [[1,1,0], [1,1,1], [1,0,1]], [[1,0,0], [1,1,1], [1,1,1]], [[1,1,1], [1,1,0], [1,1,1]], [[1,1,1], [1,1,1], [1,1,1]], ] # Generate CMs ####################################################### # returns True if there is a self-loop on any nodes has_self_loops = lambda cm: bool(len([1 for i in range(NUM_NODES) if cm[i][i] == 1])) # returns True if any node doesn't have a connection with at least one other node # note, this doesn't guarantee a weakly connected graph (ex A->B C->D, AB isn't connected to CD) has_unconnected_node = lambda cm: bool(len( [1 for i in range(NUM_NODES) if sum(cm[i])==0 and sum(np.array(cm).T.tolist()[i])==0 ])) # all cms for condition 1 cms1 = [cm for cm in unique_cms if not has_self_loops(cm) and not has_unconnected_node(cm)] # same as cms1, but each node has a self loop cms2 = [to_2d_list(cm) for cm in cms1] for i, cm in enumerate(cms2): for j in range(NUM_NODES): cm[j][j] = 1 cms2[i] = to_2d_tuple(cm) # Establish the different conditions ####################################################### condition_names = ['1A', '1B', '2A', '2B'] # sum_to_mech_map = if sum==<index of this array>, mech must be in <value @ index> conditions = { '1A':{ 'cms': cms1, 'mechanisms': [OR, AND, NULL], 'inputs_sum_to_mech_map': [[NULL], [OR], [OR, AND]] }, '1B':{ 'cms': cms1, 'mechanisms': [OR, AND, NULL, XOR], 'inputs_sum_to_mech_map': [[NULL], [OR], [OR, AND, XOR]] }, '2A':{ 'cms': cms2, 'mechanisms': [G1, G2, G3, NULL], 'inputs_sum_to_mech_map': [[NULL], [G1], [G1, G2], [G1, G2, G3]] }, '2B':{ 'cms': cms2, 'mechanisms': [G1, G2, G3, NULL, XOR], 'inputs_sum_to_mech_map': [[NULL], [G1], [G1, G2, XOR], [G1, G2, G3, XOR]] }, } # Run each condition ####################################################### for condition_name in condition_names: condition = conditions[condition_name] MECHANISMS = condition['mechanisms'] INPUTS_SUM_TO_MECH_MAP = condition['inputs_sum_to_mech_map'] CMS = condition['cms'] print('\n\nCondition: ', condition_name) seen_tpms_by_condition = {} for cm in CMS: seen_tpms_by_condition[cm] = {} seen_tpms_by_condition[cm]['seen'] = set() seen_tpms_by_condition[cm]['num_concepts'] = [] seen_tpms_by_condition[cm]['phi_concepts'] = [] seen_tpms_by_condition[cm]['phi_network'] = [] seen_tpms_by_condition[cm]['phi_main_complex'] = [] for nodes in product(MECHANISMS, repeat=NUM_NODES): # ignore systems that don't match the INPUTS_SUM_TO_MECH_MAP ignore = False for sm, mechs in enumerate(INPUTS_SUM_TO_MECH_MAP): if not all_nodes_where_incoming_sum_is_x_are_mech_y(cm, nodes, sm, mechs): ignore = True break if ignore: continue tpm = generate_tpm(nodes, cm) n_tpm = normalize_tpm(tpm) # continue next loop if this tpm has already been seen on this condition if to_2d_tuple(n_tpm) in seen_tpms_by_condition[to_2d_tuple(cm)]['seen']: continue seen_tpms_by_condition[cm]['seen'].add(to_2d_tuple(n_tpm)) # # DEBUG CODE # debug_flag = False # for debug_i, debug_cm in enumerate(motifs_mapping): # if normalize_cm(debug_cm) == normalize_cm(cm): # if debug_i == 3: # debug_flag = True # print("MOTIF: ", debug_i) # print(cm) # print(tpm) for current_state in all_activations: network = pyphi.Network(tpm, current_state, past_state, connectivity_matrix=cm) subsystem = pyphi.Subsystem(range(network.size), network) constellations = pyphi.compute.constellation(subsystem) # Record stats of interest seen_tpms_by_condition[cm]['num_concepts'].append(len(constellations)) if len(constellations) > 0: seen_tpms_by_condition[cm]['phi_concepts'].append(mean([x.phi for x in constellations])) else: seen_tpms_by_condition[cm]['phi_concepts'].append(0) seen_tpms_by_condition[cm]['phi_network'].append(pyphi.compute.big_phi(subsystem)) main = pyphi.compute.main_complex(network) seen_tpms_by_condition[cm]['phi_main_complex'].append(main.phi) # if debug_flag: # print(tpm, current_state, '--', pyphi.compute.big_phi(subsystem)) print('') # Prepare and print the results to the screen ####################################################### seen = seen_tpms_by_condition # i=motif no., m=motif's cm, row=row from `seen` printer = lambda i, m, row: ['\'%2d'%(i+1), str(m), str(len( row['seen'])), '%.2f' % (mean(row['num_concepts'])) if len(row['num_concepts'])>0 else 'null' , '%.2f' % (mean(row['phi_concepts'])) if len(row['phi_concepts'])>0 else 'null' , '%.2f' % (mean(row['phi_network'])) if len(row['phi_concepts'])>0 else 'null' , '%.2f' % (mean(row['phi_main_complex'])) if len(row['phi_network'])>0 else 'null'] with open('results.txt', 'a') as f: if condition_name in ['1A', '1B']: for i, m in enumerate(motifs_mapping): row = seen[to_2d_tuple(normalize_cm(m))] f.write('\t'.join(printer(i, m, row)) + '\n') else: for i, m in enumerate(motifs_plus_self_mapping): row = seen[to_2d_tuple(normalize_cm(m))] f.write('\t'.join(printer(i, m, row)) + '\n')