def test_attribute_mixing_matrix_multigraph(self): mapping = {"one": 0, "two": 1, "red": 2, "blue": 3} a_result = np.array([[4, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) a = nx.attribute_mixing_matrix( self.M, "fish", mapping=mapping, normalized=False ) npt.assert_equal(a, a_result) a = nx.attribute_mixing_matrix(self.M, "fish", mapping=mapping) npt.assert_equal(a, a_result / float(a_result.sum()))
def test_attribute_mixing_matrix_multigraph(self): mapping = {'one': 0, 'two': 1, 'red': 2, 'blue': 3} a_result = np.array([[4, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) a = nx.attribute_mixing_matrix(self.M, 'fish', mapping=mapping, normalized=False) npt.assert_equal(a, a_result) a = nx.attribute_mixing_matrix(self.M, 'fish', mapping=mapping) npt.assert_equal(a, a_result / float(a_result.sum()))
def test_attribute_mixing_matrix_directed(self): mapping = {"one": 0, "two": 1, "red": 2, "blue": 3} a_result = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]]) a = nx.attribute_mixing_matrix(self.D, "fish", mapping=mapping, normalized=False) np.testing.assert_equal(a, a_result) a = nx.attribute_mixing_matrix(self.D, "fish", mapping=mapping) np.testing.assert_equal(a, a_result / float(a_result.sum()))
def test_attribute_mixing_matrix_multigraph(self): mapping={'one':0,'two':1,'red':2,'blue':3} a_result=np.array([[4,0,0,0], [0,2,0,0], [0,0,0,0], [0,0,0,0]] ) a=nx.attribute_mixing_matrix(self.M,'fish', mapping=mapping, normalized=False) npt.assert_equal(a,a_result) a=nx.attribute_mixing_matrix(self.M,'fish', mapping=mapping) npt.assert_equal(a,a_result/float(a_result.sum()))
def get_compatibility_matrix(g: nx.Graph, attr_name: str): """ From Danai's heterophily paper :param g: :param attr_name: :return: """ if max(g.nodes) != g.order() - 1: g = nx.convert_node_labels_to_integers(g, first_label=0) values = set(nx.get_node_attributes(g, attr_name).values()) mapping = {val: i for i, val in enumerate(values)} # print(mapping) C = nx.attribute_mixing_matrix(g, attribute=attr_name, mapping=mapping, normalized=False) np.fill_diagonal(C, C.diagonal() / 2) D = np.diag(np.diag(C)) e = np.ones(shape=(len(mapping), 1)) h = float((e.T @ D @ e) / (e.T @ C @ e)) H = np.nan # Y = np.zeros(shape=(g.order(), len(mapping))) # for n, d in g.nodes(data=True): # attr = d[attr_name] # Y[n, mapping[attr]] = 1 # A = nx.adjacency_matrix(g) # E = np.ones(shape=(A.shape[0], len(mapping))) # # H = (Y.T @ A @ Y) / (Y.T @ A @ E) return_d = dict(homophily_ratio=h, compatibility_mat=H, attr_name=attr_name, mapping=mapping) return return_d
def update_graph(self, chosen_nt_node: int, chosen_rule: VRGRule, node_correspondence: Union[None, Dict] = None) -> None: """ Update the current graph by - removing the node corresponding to the NonTerminal - replacing that with the RHS graph of the rule - rewiring the broken edges - node labels are carried """ existing_node = chosen_nt_node logging.debug(f'Replacing node: {existing_node} with rule {chosen_rule}') chosen_nt: NonTerminal = self._gen_graph.nodes[chosen_nt_node]['nt'] assert self._gen_graph.degree_(existing_node) == chosen_nt.size, 'Degree of non-terminal must match its size' broken_edges = find_boundary_edges(self._gen_graph, {existing_node}) # find the broken edges broken_edges: Counter[tuple, int] = CustomCounter(broken_edges) # TODO change to a Counter object to speed things up assert sum(broken_edges.values()) == chosen_nt.size, f'Incorrect #broken edges: {len(broken_edges)} != {chosen_nt.size}' self.total_rewirings += broken_edges.positive_values_len() # all the broken edges need to be rewired node_count = max(self._gen_graph.nodes) + 1 # number of nodes in the present graph self._gen_graph.remove_node(existing_node) # remove the existing node from the graph node_label = {} # empty dictionary b_degs = {} # this is needed to not modify the boundary degrees of rules in place for node, d in chosen_rule.graph.nodes(data=True): # add the nodes from rule node_label[node] = node_count b_degs[node] = d['b_deg'] if 'nt' in d: self.current_non_terminal_nodes.add(node_label[node]) # add the nonterminal node to the set if 'attr_dict' in d: d = d['attr_dict'] self._gen_graph.add_node(node_label[node], **d) node_count += 1 for u, v, d in chosen_rule.graph.edges(data=True): # add edges from rule self._gen_graph.add_edge(node_label[u], node_label[v], **d) if broken_edges.positive_values_len() != 0: if self.use_fancy_rewiring: # Figure out if there are terminal nodes on both RULE and the current graph rule_terminals = [node for node, d in chosen_rule.graph.nodes(data=True) if 'nt' not in d] graph_terminal_ctr = CustomCounter() # for u, v in broken_edges: for u, v in broken_edges.elements(): node = v if u == existing_node else u if 'nt' not in self._gen_graph.nodes[node]: graph_terminal_ctr[node] += 1 # .append(node) if len(rule_terminals) > 0 and len(graph_terminal_ctr) > 0: # this is where the probabilistic matching needs to happen # rule_terminal_list = [] # we need b_deg copies of each terminal in the rules rule_terminal_ctr = CustomCounter() # we need b_deg copies of each terminal in the rules # TODO changed for rule_t in rule_terminals: b_deg = b_degs[rule_t] if b_deg > 0: rule_terminal_ctr[rule_t] = b_deg # assert graph_terminal_ctr.positive_values_len() <= rule_terminal_ctr.positive_values_len() # do the matching up while True: if graph_terminal_ctr.positive_values_len() == 0 or rule_terminal_ctr.positive_values_len() == 0: break # 1. pick a graph terminal at random and remove it graph_t = random.choice(list(graph_terminal_ctr.keys())) graph_terminal_ctr[graph_t] -= 1 # 2. pick a rule terminal based on incremental assortativity best_rule_terminal = None, np.inf # we actually dont need to calculate assortativity mixing mat from scratch here # TODO attr_mixing_mat = nx.attribute_mixing_matrix(self._gen_graph, attribute=self.attr_name, mapping=self.mapping, normalized=False) deg_mixing_mat = nx.degree_mixing_matrix(self._gen_graph, normalized=False) ###### for rule_t in rule_terminal_ctr: # calculate degree and attribute ast after edge (graph_t, node_label[rule_t]) u, v = graph_t, node_label[rule_t] attr_u, attr_v = self._gen_graph.nodes[u][self.attr_name], self._gen_graph.nodes[v][self.attr_name] new_deg_ast, new_deg_mixing_mat = incremental_degree_assortativity(g=self._gen_graph, u=u, v=v, M_curr=deg_mixing_mat) new_attr_ast, new_attr_mixing_mat = incremental_attr_assortativity(g=self._gen_graph, attr_name=self.attr_name, attr_u=attr_u, attr_v=attr_v, mapping=self.mapping, M=attr_mixing_mat) deg_ast_diff = np.abs(self.inp_deg_ast - new_deg_ast) attr_ast_diff = np.abs(self.inp_attr_ast - new_attr_ast) cost = -1 if np.isnan(deg_ast_diff) else self.alpha * deg_ast_diff if not np.isnan(attr_ast_diff): cost += (1 - self.alpha) * attr_ast_diff if cost < best_rule_terminal[1]: best_rule_terminal = rule_t, cost best_deg_mixing_mat = new_deg_mixing_mat best_attr_mixing_mat = new_attr_mixing_mat rule_t = best_rule_terminal[0] assert rule_t is not None rule_terminal_ctr[rule_t] -= 1 # .remove(rule_t) logging.debug(f'Best rule terminal {node_label[rule_t]} cost = {best_rule_terminal[1]}') # 3. Add the edge to gen_graph logging.debug(f'Adding broken edge {(node_label[rule_t], graph_t)} the fancy way') self._gen_graph.add_edge(graph_t, node_label[rule_t]) # node_label stores the actual label in gen_graph # update the mixing matrices # deg_mixing_mat = best_deg_mixing_mat.copy() # attr_mixing_mat = best_attr_mixing_mat.copy() # assert np.allclose(nx.degree_mixing_matrix(self._gen_graph, normalized=False), deg_mixing_mat) self.fancy_rewirings += 1 # fancy rewiring # 3. update b_deg for the rule terminal b_degs[rule_t] -= 1 # 4. Remove the boundary edge from list of boundary edges if (graph_t, existing_node) in broken_edges: # broken_edges.remove((graph_t, existing_node)) broken_edges[(graph_t, existing_node)] -= 1 else: # broken_edges.remove((existing_node, graph_t)) broken_edges[(existing_node, graph_t)] -= 1 # continue the regular random rewiring with the remaining broken edges broken_edges: list = list(broken_edges.elements()) # turn broken edges back into a list random.shuffle(broken_edges) # shuffle the broken edges # randomly joining the new boundary edges from the RHS to the rest of the graph - uniformly at random for node, d in chosen_rule.graph.nodes(data=True): num_boundary_edges = b_degs[node] if num_boundary_edges == 0: # there are no boundary edges incident to that node continue assert len(broken_edges) >= num_boundary_edges edge_candidates = broken_edges[: num_boundary_edges] # picking the first num_broken edges broken_edges = broken_edges[num_boundary_edges:] # removing them from future consideration for u, v in edge_candidates: # each edge is either (node_sample, v) or (u, node_sample) if u == existing_node: # u is the existing node, rewire it to node u = node_label[node] else: v = node_label[node] logging.debug(f'adding broken edge ({u}, {v})') self._gen_graph.add_edge(u, v) return
lambda g: np.mean([e for e in g.degree().values()]), # Average eccentricity lambda g: np.mean([i for i in nx.eccentricity(g).values()]), # Average closeness centrality lambda g: np.mean([e for e in nx.closeness_centrality(g).values()]), # Percentage of isolated points (i.e., degree(v) = 1) lambda g: float(len(np.where(np.array(nx.degree(g).values()) == 1)[0])) / g .order(), # Spectral radius (i.e., largest AM eigenvalue) lambda g: np.abs(nx.adjacency_spectrum(g))[0], # Spectral trace (i.e., sum of abs. eigenvalues) lambda g: np.sum(np.abs(nx.adjacency_spectrum(g))), # Label entropy, as defined in [2] lambda g: label_entropy([e[1]['type'] for e in g.nodes(data=True)]), # Mixing coefficient of attributes lambda g: np.linalg.det(nx.attribute_mixing_matrix(g, 'type')), # Avg. #vertics with eccentricity == radius (i.e., central points) lambda g: np.mean(float(len(nx.center(g))) / g.order()), # Link impurity, as defined in [2] lambda g: link_impurity(g), # Diameter := max(eccentricity) lambda g: nx.diameter(g), # Radius := min(eccentricity) lambda g: nx.radius(g) ] def link_impurity(g): """Compute link impurity of vertex-labeled graph. Parameters
with open("panama-beneficiary.pickle", "wb") as outfile: pickle.dump(panama0, outfile) cdict = {"Entities": "pink", "Officers": "blue", "Intermediaries": "green"} c = [cdict[panama0.node[n]["kind"]] for n in panama0] dzcnapy.small_attrs["node_color"] = c pos = graphviz_layout(panama0) nx.draw_networkx(panama0, pos=pos, with_labels=False, **dzcnapy.small_attrs) dzcnapy.set_extent(pos, plt) dzcnapy.plot("panama0") nx.attribute_assortativity_coefficient(panama0, "kind") nx.attribute_mixing_matrix(panama0, "kind", mapping={ "Entities": 0, "Officers": 1, "Intermediaries": 2 }) nx.attribute_assortativity_coefficient(panama0, "country") nx.degree_assortativity_coefficient(panama0) deg = nx.degree(panama0) x, y = zip(*Counter(deg.values()).items()) plt.scatter(x, y, s=100, c="pink") plt.xscale("log") plt.yscale("log") plt.legend() plt.xlim(0.9, max(x)) plt.ylim(0.9, max(y))
nx.draw(G1, node_size=250, labels=label_dict, edge_color=colors_edge_1, node_color=colors_node, with_labels=True) plt.show() # TODO: Otimizar geracao desses dicionarios partidos = {i: partidos_atuais[i] for i in range(len(lista_atuais))} mapa_partidos = {p: i for i, p in enumerate(dic_partidos.keys())} #print(G1.nodes) nx.set_node_attributes(G1, partidos, name="Partido") mixMatrix_partido = nx.attribute_mixing_matrix(G1, "Partido", mapping=mapa_partidos) #print("\tMatriz de Mixagem (partidos):", mixMatrix) #print(mixMatrix.shape) #print(mapa_partidos) alinhamentos = { i: dic_partidos[partidos_atuais[i]] for i in range(len(lista_atuais)) } mapa_alinhamentos = {'apoio': 0, 'medio': 1, 'oposicao': 2} #print(alinhamentos) nx.set_node_attributes(G1, alinhamentos, name="Alinhamento") mixMatrix_alinhamento = nx.attribute_mixing_matrix(G1, "Alinhamento",
attr_list = [ #Average degree lambda g : np.mean([e for e in g.degree().values()]), # Average eccentricity lambda g : np.mean([i for i in nx.eccentricity(g).values()]), # Average closeness centrality lambda g : np.mean([e for e in nx.closeness_centrality(g).values()]), # Percentage of isolated points (i.e., degree(v) = 1) lambda g : float(len(np.where(np.array(nx.degree(g).values())==1)[0]))/g.order(), # Spectral radius (i.e., largest AM eigenvalue) lambda g : np.abs(nx.adjacency_spectrum(g))[0], # Spectral trace (i.e., sum of abs. eigenvalues) lambda g : np.sum(np.abs(nx.adjacency_spectrum(g))), # Label entropy, as defined in [2] lambda g : label_entropy([e[1]['type'] for e in g.nodes(data=True)]), # Mixing coefficient of attributes lambda g : np.linalg.det(nx.attribute_mixing_matrix(g,'type')), # Avg. #vertics with eccentricity == radius (i.e., central points) lambda g : np.mean(float(len(nx.center(g)))/g.order()), # Link impurity, as defined in [2] lambda g : link_impurity(g), # Diameter := max(eccentricity) lambda g : nx.diameter(g), # Radius := min(eccentricity) lambda g : nx.radius(g)] def link_impurity(g): """Compute link impurity of vertex-labeled graph. Parameters ----------
"urm": None, "pronoun_urm": None } dict_node_to_attribute = nx.get_node_attributes(G, attribute) ## TODO: Double check the NA individuals nodeset = dict_node_to_attribute.keys() if NA_by_attribute[attribute]: ## If we want to filter the nodeset by removing a single type of value for this attribute nodeset = [ node for node, value in dict_node_to_attribute.items() if value != NA_by_attribute[attribute] ] e_ij_all_normalized = nx.attribute_mixing_matrix( G, attribute, nodes=nodeset, mapping=mapping[attribute]) #e_ij = nx.attribute_mixing_matrix(G,attribute,mapping=mapping) attribute_assortativity_numbers_matrix = np.zeros( (len(mapping[attribute]), len(mapping[attribute])), dtype=int, order='C') for edge in G.edges(data=True): #print(edge) if edge[0] in nodeset and edge[1] in nodeset: attribute_assortativity_numbers_matrix[mapping[attribute][ dict_node_to_attribute[edge[0]]]][mapping[attribute][ dict_node_to_attribute[edge[1]]]] += 1 ## This network is undirected, so we need to count the edge on the other way round too attribute_assortativity_numbers_matrix[mapping[attribute][ dict_node_to_attribute[edge[1]]]][mapping[attribute][