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()))
Exemplo n.º 2
0
 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()))
Exemplo n.º 3
0
 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()))
Exemplo n.º 4
0
 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()))
Exemplo n.º 5
0
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
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
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))
Exemplo n.º 9
0
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",
Exemplo n.º 10
0
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
    ----------
Exemplo n.º 11
0
        "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][