def subtrahend(orbit1, orbit2, nets, auts, invs, allowed_aspects='all'): ''' Returns the subtrahend for orbit2 in orbit equations (the value that is substracted in the upper part of the binomial coefficient on theleft sides of the orbit equation) Parameters ---------- orbit1, orbit2 : tuple (n_nodes, net_index, node_orbit_index) These can extract from the output of orbit_equations, n_nodex, net_index, and node_orbit_index should match those of parameter auts nets : dict (key: n_nodes, value: list of networks) graphlets, as produced by graphlets auts : dd (key: (n_nodes, net_index, node), value: node_orbit_index) as produced by automorphism_orbits Returns ------- sub_max : int Notes ----- assumes orbit2 has at most the same number of nodes as orbit1 ''' sub_max = 0 n_nodes1 = orbit1[0] n_nodes2 = orbit2[0] net1 = nets[n_nodes1][orbit1[1]] net2 = nets[n_nodes2][orbit2[1]] the_node = orbit1[2] layers = net1.slices[1] nodes = net1.slices[0] - set([the_node]) for partition in partitions_with_remainder(nodes, n_nodes2 - 1): sub = 0 for nodes_s in partition: nodes_g = set(nodes_s) | set([the_node]) sub_net = pymnet.subnet(net1, nodes_g, layers) ci_sub = str( pymnet.get_complete_invariant(sub_net, allowed_aspects=allowed_aspects)) if ci_sub in invs and invs[ci_sub] == (n_nodes2, orbit2[1]): iso = pymnet.get_isomorphism(sub_net, net2, allowed_aspects=allowed_aspects) if the_node in iso[0]: iso_node = iso[0][the_node] else: iso_node = the_node if auts[n_nodes2, orbit2[1], iso_node] == orbit2[2]: sub += 1 sub_max = max(sub_max, sub) return sub_max
def orbit_counts(n, node0, net, nets, orbits, auts, invs, orbit_list, allowed_aspects='all'): ''' Computes the orbit counts for node0 in net Parameters ---------- node0 : node net : network nets : dict (key: n_nodes, value: list of networks) graphlets orbits : dd (key: (node, orbit), value: count) dictionary where the counts will be stored auts : dd (key: (n_nodes, net_index, node), value: node) automorphism orbits invs : dict (key: str(complete invariant), value: tuple(n_nodes, net_index in nets)) complete invariants of the graphlets orbit_list : list of orbits allowed_aspects : list, string the aspects that can be permutated when computing isomorphisms ''' for orbit in orbit_list: orbits[node0, orbit] = 0 layers = net.slices[1] node_sets = touching_orbit_nodes(node0, net, n) for nodes_s in node_sets: sub_net = pymnet.subnet(net, nodes_s, layers) ci_sub = str( pymnet.get_complete_invariant(sub_net, allowed_aspects=allowed_aspects)) i = invs[ci_sub][1] n_nodes = invs[ci_sub][0] nw = nets[n_nodes][i] iso = pymnet.get_isomorphism(sub_net, nw, allowed_aspects=allowed_aspects) if node0 in iso[0]: orbits[node0, (n_nodes, i, auts[n_nodes, i, iso[0][node0]])] += 1 else: orbits[node0, (n_nodes, i, auts[n_nodes, i, node0])] += 1
def orbit_name(node, net, nets, invs, auts, allowed_aspects='all'): ''' finds the name of the orbit given node and net ''' ci = str( pymnet.get_complete_invariant(net, allowed_aspects=allowed_aspects)) i, j = invs[ci] net_i = nets[i][j] iso = pymnet.get_isomorphism(net, net_i, allowed_aspects=allowed_aspects, include_fixed=True) k = auts[i, j, iso[0][node]] return (i, j, k)
def coefficient_help(nodes, the_node, both_orbit_nodes, orbit1, orbit2, net, nets, auts, invs, allowed_aspects='all'): ''' helper function for coefficient ''' coef = 0 nodes_a = net.slices[0] layers = net.slices[1] net1 = nets[orbit1[0]][orbit1[1]] net2 = nets[orbit2[0]][orbit2[1]] n_nodes1 = len(net1.slices[0]) for node_comb in itertools.combinations(nodes, n_nodes1 - len(both_orbit_nodes)): nodes_s2 = nodes_a - set(node_comb) nodes_s1 = (nodes_a - nodes_s2) | set(both_orbit_nodes) sub1 = pymnet.subnet(net, nodes_s1, layers) sub2 = pymnet.subnet(net, nodes_s2, layers) ci_sub1 = str( pymnet.get_complete_invariant(sub1, allowed_aspects=allowed_aspects)) ci_sub2 = str( pymnet.get_complete_invariant(sub2, allowed_aspects=allowed_aspects)) if not ci_sub1 in invs or not ci_sub2 in invs: continue if invs[ci_sub1] == (orbit1[0], orbit1[1]) and invs[ci_sub2] == (orbit2[0], orbit2[1]): iso1 = pymnet.get_isomorphism(sub1, net1, allowed_aspects=allowed_aspects) iso2 = pymnet.get_isomorphism(sub2, net2, allowed_aspects=allowed_aspects) if the_node in iso1[0]: iso_node1 = iso1[0][the_node] else: iso_node1 = the_node if the_node in iso2[0]: iso_node2 = iso2[0][the_node] else: iso_node2 = the_node if auts[orbit1[0], orbit1[1], iso_node1] == orbit1[2] and auts[orbit2[0], orbit2[1], iso_node2] == orbit2[2]: coef += 1 return coef
def orbit_equations(n, nets, auts, invs, allowed_aspects='all'): ''' Generate orbit equations for up to n nodes The equations are in following formatting: orbits : this represents node orbits of graphlets Parameters ---------- n : int maximum number of nodes nets : dict (key: n_nodes, value: list of nets) graphlets, as returned by graphlets auts : dd (key: (n_nodes, net_index, node), value: node) automorphisms, as returned by automorphism_orbits invs : dict (key: str(complete invariant), value: tuple(n_nodes, net_index in nets)) complete invariants of the graphlets, as returned by graphlets allowed_aspects : list, string the aspects that can be permutated when computing isomorphisms Returns ------- orbit_eqs : dict (key: orbits, value: dict (key: orbit, value: coefficient)) ''' orbit_eqs = dd() orbit_lists = list_orbits(auts) for n_nodes1 in range(2, min(n + 1, 4)): for orbit in orbit_lists[n_nodes1]: node1 = orbit[2] for n_nodes in orbit_lists: comb_n_nodes = n_nodes1 + n_nodes - 1 if comb_n_nodes <= n: for orbit2 in orbit_lists[n_nodes]: if ((orbit, 1), (orbit2, 1)) in orbit_eqs: continue new_nets = {} new_orbits = set() comb_nets = combine_orbits( orbit, orbit2, nets, allowed_aspects=allowed_aspects) if comb_nets == None: continue for k in range(len(comb_nets)): comb_nets[k] = (comb_nets[k], [node1]) merge_nets = {} min_nodes = max([n_nodes1, n_nodes]) + 1 merge_nets[comb_n_nodes] = comb_nets for m in range( comb_n_nodes, min_nodes, -1 ): #TODO: make this merge thingy smarter, use combinations merge_nets[m - 1] = [] for m_net in merge_nets[m]: merge_nets[m - 1] += merge_nodes( m_net[1], m_net[0], allowed_aspects=allowed_aspects) comb_nets += merge_nets[m - 1] add_e_nets = [] for k in range(len(comb_nets)): c_net = comb_nets[k][0] both_orbit_nodes = comb_nets[k][1] nets_e = add_possible_edges( both_orbit_nodes, c_net) for net_e in nets_e: add_e_nets.append((net_e, both_orbit_nodes)) comb_nets += add_e_nets for comb_net in comb_nets: ci_comb = str( pymnet.get_complete_invariant( comb_net[0], allowed_aspects=allowed_aspects)) iso_net = invs[ci_comb] iso = pymnet.get_isomorphism( comb_net[0], nets[iso_net[0]][iso_net[1]], allowed_aspects=allowed_aspects) if node1 in iso[0]: node_o = iso[0][node1] else: node_o = node1 new_orbit = (iso_net[0], iso_net[1], auts[iso_net[0], iso_net[1], node_o]) if not new_orbit in new_orbits: new_orbits.add(new_orbit) new_nets[new_orbit] = comb_net if orbit == orbit2: times = 2 key = ((orbit, times)) else: times = 1 key = ((orbit2, 1), (orbit, 1)) orbit_eqs[key] = {} for i in new_orbits: coef = coefficient(node1, new_nets[i][1], orbit, orbit2, new_nets[i][0], nets, auts, invs, allowed_aspects=allowed_aspects) if coef > 0: orbit_eqs[key][i] = coef return orbit_eqs
def orbit_counts_all(net, n, nets, invs, auts, orbit_list, allowed_aspects='all'): ''' Computes the orbit counts for all the nodes in net Parameters ---------- net : network n : int max number of nodes nets : dict (key: n_nodes, value: list of networks) Graphlets, as produced by graphlets invs : dict (key: str(complete invariant), value: tuple(n_nodes, net_index in nets)) complete invariants of the graphlets, as produced by graphlet auts : dd (key: (n_nodes, net_index, node), value: node) automorphisms, as produced by automorphism_orbits orbit_list : list of orbits as returned by ordered_orbit_list allowed_aspects : list, string the aspects that can be permutated when computing isomorphisms Returns ------- orbits : dd (key: (node, orbit), value: count) Orbit counts for all the nodes Notes ----- Should be faster than orbit_counts if the counts are computed for all (/ most of) the nodes ''' nodes = net.slices[0] layers = net.slices[1] orbits = dd() for node in nodes: for orbit in orbit_list: orbits[node, orbit] = 0 processed = set() for node0 in nodes: node_sets = set() set_p = set([frozenset([node0])]) for _ in range(n - 1): set_c = set() for p in set_p: for node_p in p: for layer in layers: node_o = net.__getitem__((node_p, layer)) for neighbor in node_o.iter_total(): if not (neighbor[0] in p or neighbor[0] in processed): set_n = frozenset(p | set([neighbor[0]])) set_c.add(set_n) node_sets = node_sets.union(set_c) set_p = set_c.copy() processed.add(node0) for node_comb in node_sets: sub_net = pymnet.subnet(net, node_comb, layers) ci_sub = str( pymnet.get_complete_invariant(sub_net, allowed_aspects=allowed_aspects)) if ci_sub not in invs: pymnet.draw(sub_net) print(len(invs)) i = invs[ci_sub][0] j = invs[ci_sub][1] nw = nets[i][j] iso = pymnet.get_isomorphism(sub_net, nw, allowed_aspects=allowed_aspects) for node in node_comb: if node in iso[0]: orbits[node, (i, j, auts[i, j, iso[0][node]])] += 1 else: orbits[node, (i, j, auts[i, j, node])] += 1 for layer in layers: nls = list(net[node0, :, layer]) for node1 in nls: net[node0, node1[0], layer] = 0 #remove edges return orbits