def draw_edges(graph: nx.Graph, node_colors: list, node_positions: list) -> None: """Draw the network edges. If an edge has two nodes of the same color, use that color for the edge, otherwise make the edge a light gray. """ nodes = graph.nodes() node_color_lookup = {} for (i, node) in enumerate(nodes): node_color_lookup[node] = node_colors[i] edge_colors = [] for (i, edge) in enumerate(graph.edges()): (n1, n2) = edge c1 = node_color_lookup[n1] c2 = node_color_lookup[n2] edge_colors.append(c2) continue if c1 == c2: edge_colors.append(c1) else: edge_colors.append('#aaaaaa') edge_colors = [node_color_lookup[e[1]] for e in graph.edges()] nx.draw_networkx_edges( G=graph, pos=node_positions, with_labels=False, edge_color=edge_colors, alpha=0.025, )
def draw_pyplot_graph(graph: nx.Graph): """Will open a window with the NetworkX graph object drawn Given NetworkX graph object, calls matplotlib.pyplot to draw then show the graph object Args: graph: NetworkX Graph object, or derivative Requires: import matplotlib.pyplot as plt """ # Create dict of key=node, value=pseudonode status (bool) pns = {v: d["pseudonode"] for _, v, d in graph.edges(data=True)} # color_map is an ordered list, where order is for `node in graph` # This is the same order nx.draw encounters nodes color_map = [] for node in graph: if pns[node]: # If node is a pseudonode ... color_map.append("blue") else: color_map.append("green") edge_labels = {(u, v): d["cost"] for u, v, d in graph.edges(data=True)} pos = nx.spring_layout(graph) nx.draw(graph, pos, node_color=color_map, with_labels=True, font_size=7) nx.draw_networkx_edge_labels(graph, pos, edge_labels=edge_labels, label_pos=0.3, font_size=7) plt.show()
def count_graph_distance(g1: nx.Graph, g2: nx.Graph, mapping: dict, reverse_mapping: dict, sub: bool): d_vertex = 0 d_edge = 0 symbols1 = nx.get_node_attributes(g1, 'symbol') symbols2 = nx.get_node_attributes(g2, 'symbol') # count distance of vertices for node1 in g1.nodes(): if mapping[node1] == -1: d_vertex += 1 elif symbols1[node1] != symbols2[mapping[node1]]: d_vertex += 1 if not sub: # not sub graph distance for node2 in g2.nodes(): if reverse_mapping[node2] == -1: d_vertex += 1 # count distance of edges for first, second in g1.edges(): if mapping[first] == -1 or mapping[second] == -1 or not g2.has_edge( mapping[first], mapping[second]): d_edge += 1 if not sub: for first, second in g2.edges(): if reverse_mapping[first] == -1 or reverse_mapping[second] == -1 \ or not g1.has_edge(reverse_mapping[first], reverse_mapping[second]): d_edge += 1 return d_vertex + d_edge
def preprocess_transition_probs(sc: SparkContext, graph: nx.Graph, p, q, is_directed): """ Preprocessing of transition probabilities for guiding the random walks. """ alias_nodes = {} for node in graph.nodes(): unnormalized_probs = [ graph[node][nbr]['weight'] for nbr in sorted(graph.neighbors(node)) ] norm_const = sum(unnormalized_probs) normalized_probs = [ float(u_prob) / norm_const for u_prob in unnormalized_probs ] alias_nodes[node] = alias_setup(normalized_probs) b_graph = sc.broadcast(graph) if is_directed: alias_edges = sc.parallelize(graph.edges(), 1000)\ .map(lambda uv: ((uv[0], uv[1]), get_alias_edge(uv[0], uv[1], b_graph.value, p, q)))\ .collectAsMap() else: alias_edges = sc.parallelize(graph.edges(), 1000)\ .flatMap(lambda uv: [ ((uv[0], uv[1]), get_alias_edge(uv[0], uv[1], b_graph.value, p, q)), ((uv[1], uv[0]), get_alias_edge(uv[1], uv[0], b_graph.value, p, q)) ]).collectAsMap() return alias_nodes, alias_edges
def _assert_graphs_nx_equal(g1: nx.Graph, g2: nx.Graph): # Check number of nodes and edges assert g1.number_of_nodes() == g2.number_of_nodes() assert g1.number_of_edges() == g2.number_of_edges() # Check node features for (node_id_1, node_features_1), (node_id_2, node_features_2) in \ zip(g1.nodes(data='features'), g2.nodes(data='features')): assert node_id_1 == node_id_2 assert (node_features_1 is not None) == (node_features_2 is not None) if node_features_1 is not None and node_features_2 is not None: torch.testing.assert_allclose(node_features_1, node_features_2) # Check edge features for (sender_id_1, receiver_id_1, edge_features_1), (sender_id_2, receiver_id_2, edge_features_2) in \ zip(g1.edges(data='features'), g2.edges(data='features')): assert sender_id_1 == sender_id_2 assert receiver_id_1 == receiver_id_2 assert (edge_features_1 is not None) == (edge_features_2 is not None) if edge_features_1 is not None and edge_features_2 is not None: torch.testing.assert_allclose(edge_features_1, edge_features_2) # Check graph features assert has_global_features(g1) == has_global_features(g2) if has_global_features(g1) and has_global_features(g2): torch.testing.assert_allclose(g1.graph['features'], g2.graph['features'])
def merge_mwvc_constraints(agt1: str, G1: nx.Graph, agt2: str, G2: nx.Graph) -> (nx.Graph, nx.Graph): """ Merge the weights associated to the nodes of type 'dec_var' that have the same 'name'. It assigns :param agt1: The name of agent 1 :param G1: The gadget graph associated to agent 1 :param agt2: The name of agent 2 :param G2: The gadget graph associated to agent 2 :return: The pairs of gadget (gadget1 and gadget2) associated to agents 1 and 2, reps. processed after the merging operation. """ shared_dec_vars = [ n for n in G1.nodes() for m in G2.nodes() if n == m and G1.nodes[n]['type'] == 'dec_var' ] for u in shared_dec_vars: if agt1 <= agt2: G1.nodes[u]['weight'] += G2.nodes[u]['weight'] for e in G2.edges(u): G1.add_edge(e[0], e[1], w=G2.get_edge_data(*e)['w']) G2.remove_node(u) else: G2.nodes[u]['weight'] += G1.nodes[u]['weight'] for e in G1.edges(u): G2.add_edge(e[0], e[1], w=G1.get_edge_data(*e)['w']) G1.remove_node(u) return G1, G2
def solveClique(G: nx.Graph) -> list: """ Solves the maximum clique problem. :param G: undirected graph :return: List of nodes """ clique = Model('Clique') # Variable X = dict() for u in G.nodes(): X[u] = clique.addVar(vtype=GRB.BINARY, name=f'X_{u}') # Constraints for u in G.nodes(): for v in G.nodes(): if (((u,v) not in G.edges()) or ((v,u) not in G.edges())) and (u != v): clique.addConstr(X[u] + X[v], GRB.LESS_EQUAL, 1) # Objective function clique.setObjective(quicksum(X[u] for u in G.nodes()), sense=GRB.MAXIMIZE) clique.update() clique.optimize() if clique.status == GRB.OPTIMAL: solution = list() for u in G.nodes(): if round(clique.getVarByName(f'X_{u}').x, 0) == 1: solution.append(u) return solution else: return None
def ic_diffuse(g: nx.Graph, activated1, activated2): free_nodes = set(g.graph['free']) new_activated1 = [] new_activated2 = [] while activated1 + activated2: if activated1: node = activated1.pop(0) for edge in g.edges(node, data=True): if edge[1] in free_nodes: r = np.random.random() if r < edge[2]['w']: # node is activated new_activated1.append(edge[1]) activate(g, edge[1], 1) free_nodes.remove(edge[1]) if activated2: node = activated2.pop(0) for edge in g.edges(node, data=True): if edge[1] in free_nodes: r = np.random.random() if r < edge[2]['w']: # node is activated new_activated2.append(edge[1]) activate(g, edge[1], 2) free_nodes.remove(edge[1]) return new_activated1, new_activated2
def calculate_internal_external_densities( graph: nx.Graph, partitions: Dict[Any, Any], weight_attribute: str = 'weight' ) -> Tuple[Dict[Any, List[float]], Dict[Any, List[float]]]: """ Calculates the internal and external densities given a graph and a node membership dictionary. Density is defined by 'How to Make the Team: Social Networks vs. Demography as Criteria for Designing Effective Teams' as being the mean strength of tie between members of the set. In other words, density is the normalized average of edge weights by node. For a given node, the density is the sum of all edge weights divided by the maximum edge weight for that node. For internal density, only the edge's whose target node is in the same membership group will be summed. Similarly, for external density, only the edge's whose target node is not in the same membership group will be summed. See also: Reagans, R., Zuckerman, E., & McEvily, B. (2004). How to Make the Team: Social Networks vs. Demography as Criteria for Designing Effective Teams. Administrative Science Quarterly, 49(1), 101–133. https://doi.org/10.2307/4131457 :param graph: A weighted graph that the internal density will be calculated over :param Dict[any, int] partitions: A dictionary for the graph with each key being a node id and each value is the membership for that node id. Often this will be a partition dictionary calculated from topologic.louvain.best_partition :param str weight_attribute: The key to the weight column on the graph's edges :return: A tuple of two dictionaries. The first is the internal density and the second is the external density :rtype: Tuple[Dict[Any, List[float]], Dict[Any, List[float]]] """ if not nx.is_weighted(graph, weight=weight_attribute): raise ValueError('The graph must be weighted.') # build a dictionary where the key is a membership_id and the value is a list of nodes that belong to that # membership membership_inverted: Dict[Any, List[Any]] = collections.defaultdict(list) for key in partitions.keys(): membership_inverted[partitions[key]].append(key) internal_density: Dict[Any, List[float]] = collections.defaultdict(list) external_density: Dict[Any, List[float]] = collections.defaultdict(list) for partition_id in membership_inverted.keys(): for node in membership_inverted[partition_id]: max_weight = max((weight for source, target, weight in graph.edges( node, data=weight_attribute))) for source, target, weight in graph.edges(node, data=weight_attribute): target_partition = partitions[target] density_for_node = weight / max_weight if target_partition == partition_id: internal_density[partition_id].append(density_for_node) else: external_density[partition_id].append(density_for_node) return internal_density, external_density
def extract_subgraph_by_bond_type( g: nx.Graph, bond_types: List[str], filter_dataframe: bool = True, update_coords: bool = True, recompute_distmat: bool = False, inverse: bool = False, return_node_list: bool = False, ) -> Union[nx.Graph, List[str]]: """Extracts a subgraph from a graph based on a list of allowable bond types. :param g: The graph to extract the subgraph from. :type g: nx.Graph :param bond_types: List of allowable bond types. :type bond_types: List[str] :param filter_dataframe: Whether to filter the pdb_df of the graph, defaults to True :type filter_dataframe: bool, optional :param update_coords: Whether to update the coordinates of the graph. Defaults to True. :type update_coords: bool :param recompute_distmat: Whether to recompute the distance matrix of the graph. Defaults to False. :type recompute_distmat: bool :param inverse: Whether to inverse the selection, defaults to False :type inverse: bool, optional :param return_node_list: Whether to return the node list, defaults to False :type return_node_list: bool, optional :return: The subgraph or node list if return_node_list is True. :rtype: Union[nx.Graph, List[str]] """ node_list: List = [] for u, v, d in g.edges(data=True): for bond_type in list(d["kind"]): if bond_type in bond_types: node_list.append(u) node_list.append(v) node_list = list(set(node_list)) log.debug(f"Found {len(node_list)} nodes in the bond type subgraph.") # Remove bond annotations for u, v, d in g.edges(data=True): for bond in list(d["kind"]): if not inverse: if bond not in bond_types: d["kind"].discard(bond) elif inverse: if bond in bond_types: d["kind"].discard(bond) return extract_subgraph_from_node_list( g, node_list, filter_dataframe=filter_dataframe, inverse=inverse, return_node_list=return_node_list, recompute_distmat=recompute_distmat, update_coords=update_coords, )
def update_cost( # pylint: disable=too-many-arguments G: nx.Graph, gdf: gpd.GeoDataFrame, edge_df: Optional[gpd.GeoDataFrame] = None, cost_attr: Optional[str] = "cost", weight_attr: Optional[str] = "weight", key_attr: Optional[str] = "key", ) -> nx.Graph: """Update the cost of edges the graph from a geo dataframe. Args: G: Input graph. Must have a geometry attribute on the edges. gdf: Must contain geometry column and value column. edge_df: The edge geo dataframe of the graph. Other Args: cost_attr: Name of the cost function. weight_attr: Name of the weight function. key_attr: Name of the key for multi graphs. Returns: Graph with updated cost attribute. """ # convert G to geodataframe if edge_df is None: # for a multigraph, remember the keys for u, v, k in G.edges(keys=True): G[u][v][k][key_attr] = k # # create a geodataframe edge_df = ox.graph_to_gdfs(G, nodes=False, fill_edge_geometry=True) edge_df = edge_df.rename(columns=dict(u="source", v="target")) # check the crs of geometries if edge_df.crs is None and not gdf.crs is None: edge_df.crs = gdf.crs elif gdf.crs is None and not edge_df.crs is None: gdf.crs = edge_df.crs # get intersection of the geodataframes logging.info("%s rows in edge dataframe", len(edge_df)) join = gpd.sjoin(edge_df, gdf, how="left") logging.info("%s rows in join dataframe", len(join)) edges_in_join = zip(join["source"], join["target"]) for u, v in G.edges(): assert (u, v) in edges_in_join or (v, u) in edges_in_join # group the edges and take average pollution for key, value in ( join.groupby(["source", "target", "key"])[cost_attr].mean().iteritems() ): i, j, k = key[0], key[1], key[2] G[i][j][k]["gamma"] = value if value >= 0 else 0 G[i][j][k][cost_attr] = value * G[i][j][k][weight_attr] return G
class Electrical_network(): """ Electrical Network: graph, power injections, electrical state (phases and frequencies) inputs: list of buses (id, {dict}), list of lines (id, {dict}) """ def __init__(self, buses, lines): # create networkx graph self.graph = Graph() self.graph.add_nodes_from(buses) self.graph.add_edges_from(lines) self.state = State(self.graph.number_of_nodes()) self.sm_id = filter(lambda n: self.graph.nodes[n]['sm'] == True, self.graph.nodes) self.load_id = filter(lambda n: self.graph.nodes[n]['sm'] == False, self.graph.nodes) # unweighted incidence in shape (|nodes| x |edges|), column ordering is produced by graph.edges self.incidence = incidence_matrix(self.graph, oriented=True) self.node_coord = np.array( [self.graph.nodes[n]['coord'] for n in self.graph.nodes]) self.edge_coord = np.array([ (self.node_coord[e[0]] + self.node_coord[e[1]]) / 2. for e in self.graph.edges() ]) def get_P(self): return np.array( [self.graph.nodes[n]['power'] for n in self.graph.nodes]) # inertia and damping coeffs, ordered according to sm_id and load_id def get_I_sm(self): return np.array([self.graph.nodes[n]['inertia'] for n in self.sm_id]) def get_D_sm(self): return np.array([self.graph.nodes[n]['damping'] for n in self.sm_id]) def get_D_load(self): return np.array([self.graph.nodes[n]['damping'] for n in self.load_id]) # edge susceptance, edge ordering is produced by graph.edges def get_active_susceptance(self): return diags([ self.graph[e[0]][e[1]]['susceptance'] * int(self.graph[e[0]][e[1]]['status']) for e in self.graph.edges() ]) # edge susceptance, edge ordering is produced by graph.edges def get_susceptance(self): return diags([ self.graph[e[0]][e[1]]['susceptance'] for e in self.graph.edges() ])
def calculate_dot_product_similarity(sub_graph: nx.Graph, super_graph: nx.Graph): a_values = np.ones(len(sub_graph.nodes()) + len(sub_graph.edges())) b_values = np.zeros(len(a_values)) for i, node in enumerate(sub_graph.nodes()): if node in super_graph.nodes(): b_values[i] = 1 for i, edge in enumerate(sub_graph.edges()): if ParsemisMiner.graph_has_edge(super_graph, sub_graph, edge): b_values[i + len(sub_graph.nodes())] = 1 return np.prod(np.column_stack( (a_values, b_values)), axis=1).sum() / len(a_values)
def graph_to_list_differences(g: nx.Graph, original_graph_complement: nx.Graph): """ Converte um grafo para a sua forma binária considerando apenas as arestas que foram adicionadas em relação ao seu original. """ complement_edges = list(original_graph_complement.edges()) graph_edges = list(g.edges()) bin_differences_list = [ 1 if e in graph_edges and complement_edges else 0 for e in complement_edges ] # List_Gr = [0 for e in Complement.edges() if e in Gr.edges()] return bin_differences_list
def planarize(G: nx.Graph): ''' Takes a graph with node embeddings in R^2 and removes random edges until planar. ''' pos = nx.get_node_attributes(G, 'pos') assert pos != {}, 'planarize() needs a node embedding' def on_segment(p, q, r): if r[0] <= max(p[0], q[0]) and r[0] >= min(p[0], q[0]) and r[1] <= max( p[1], q[1]) and r[1] >= min(p[1], q[1]): return True return False def orientation(p, q, r): val = ((q[1] - p[1]) * (r[0] - q[0])) - ((q[0] - p[0]) * (r[1] - q[1])) if val == 0: return 0 return 1 if val > 0 else -1 def intersects(seg1, seg2): p1, q1 = seg1 p2, q2 = seg2 o1 = orientation(p1, q1, p2) o2 = orientation(p1, q1, q2) o3 = orientation(p2, q2, p1) o4 = orientation(p2, q2, q1) if o1 != o2 and o3 != o4: return True if o1 == 0 and on_segment(p1, q1, p2): return True if o2 == 0 and on_segment(p1, q1, q2): return True if o3 == 0 and on_segment(p2, q2, p1): return True if o4 == 0 and on_segment(p2, q2, q1): return True return False deleted = set() for e1 in G.edges(): for e2 in G.edges(): if not (e1 in deleted or e2 in deleted or e1[0] in e2 or e1[1] in e2): e1_pos = (pos[e1[0]], pos[e1[1]]) e2_pos = (pos[e2[0]], pos[e2[1]]) if intersects(e1_pos, e2_pos): deleted.add(e1) G.remove_edges_from(deleted) return G
def check_embedding(Q, A, emb, **args): from networkx import Graph, is_connected check_embedding.warning = None Qg = Graph() Ag = Graph() Qg.add_edges_from(Q) Ag.add_edges_from(A) qubhits = 0 footprint = set() var = {} for x in Qg: try: embx = emb[x] except KeyError: check_embedding.errcode = "missing chain" return False for q in embx: var[q] = x footprint.update(embx) qubhits += len(embx) if not is_connected(Ag.subgraph(embx)): check_embedding.errcode = "broken chain for %s: (%s)" % (x, embx) return False if len(footprint) != qubhits: check_embedding.errcode = "overlapped chains" return False Qv = Graph() for p, q in Ag.edges(): try: Qv.add_edge(var[p], var[q]) except KeyError: continue for x, y in Qg.edges(): if not Qv.has_edge(x, y): check_embedding.errcode = "missing edge" return False for x, chain in args.get("fixed_chains", {}).items(): if set(chain) != set(emb[x]): check_embedding.errcode = "fixed chain mismatch" return False for x, domain in args.get("restrict_chains", {}).items(): if not set(domain) >= set(emb[x]): check_embedding.warning = "restrict chain mismatch" return True
def draw_pyplot_graph(graph: nx.Graph): """Will open a window with the NetworkX graph object drawn Given NetworkX graph object, calls matplotlib.pyplot to draw then show the graph object Args: graph: NetworkX Graph object, or derivative Requires: import matplotlib.pyplot as plt """ # Node colouring + Pseudonode handling # Create dict keyed by node, value is pseudonode status (bool) pns = {v: d["pseudonode"] for _, v, d in graph.edges(data=True)} # color_map is an ordered list, where order is for `node in graph` # This is the same order nx.draw encounters nodes color_map = [ "green" if not node in list(pns.keys()) else "blue" if pns[node] else "green" for node in graph ] # Edge labelling edge_labels = {(u, v): d["cost"] if d["cost"] > 0 else "" for u, v, d in graph.edges(data=True)} # Edge Colouring edge_color = nx.get_edge_attributes(graph, "color").values() # Edge weight edge_weight = nx.get_edge_attributes(graph, "weight").values() pos = nx.spring_layout(graph) nx.draw( graph, pos, node_color=color_map, edge_color=edge_color, width=list(edge_weight), with_labels=True, font_size=7, ) nx.draw_networkx_edge_labels(graph, pos, edge_labels=edge_labels, label_pos=0.3, font_size=7) plt.show()
def initial_flow(G: nx.Graph, KE: float = 1., scale_distribution: Callable = None): ''' Construct divergence-free initial conditions with energies at specified length-scales. scale_distribution: probability measure on [0, 1] (default uniform) ''' assert KE >= 0, 'Specify nonnegative kinetic energy' if scale_distribution is None: scale_distribution = lambda x: 1. N = len(G.edges()) P = gds.edge_gds( G).leray_projector # TODO: assumes determinism of construction freqs, spec_fun = edge_power_spectrum(G) dist = np.array( list( map(scale_distribution, (freqs - freqs.min()) / (freqs.max() - freqs.min())))) def f(x): return np.linalg.norm(spec_fun(P @ x) - dist) x0 = np.random.uniform(size=N) sol = minimize(f, x0) u = P @ sol.x u *= np.sqrt(KE / np.dot(u, u)) return u
def _prepare_data(self, g_netx: nx.Graph, custom_node_labels: Dict) -> Tuple[List, List, List, nx.graph.EdgeView]: """Create the scatter plot data from a NetworkX Graph. Args: g_netx (nx.Graph): custom_node_labels (Dict): """ graph_components = [comp for comp in nx.connected_components(g_netx)] graph_edges = g_netx.edges() # Prepare the node groups and colors communities_dict = {} for community_ind, graph_component in enumerate(graph_components): for node in graph_component: if custom_node_labels: communities_dict[node] = custom_node_labels[node] else: communities_dict[node] = community_ind nodes_with_colors = [] node_labels = [] for node in g_netx.nodes(): labels_current = node node_labels.append("Node: {}".format(labels_current)) try: nodes_with_colors.append(communities_dict[node]) except KeyError: print("Node %d in small community" % node) return graph_components, nodes_with_colors, node_labels, graph_edges
async def populate_exchange_graph(graph: nx.Graph, exchange: ccxt.Exchange, log=True, fees=False, suppress=None, depth=False, invocation_id=0) -> nx.DiGraph: """ Returns a Networkx DiGraph populated with the current ask and bid prices for each market in graph (represented by edges) """ if suppress is None: suppress = ['markets'] adapter = LoadExchangeGraphAdapter(logger, { 'count': invocation_id, 'exchange': exchange.id }) result = nx.DiGraph() tasks = [ _add_weighted_edge_to_graph(exchange, edge[2]['market_name'], result, adapter, log=log, fees=fees, suppress=suppress, depth=depth) for edge in graph.edges(data=True) ] await asyncio.wait(tasks) await exchange.close() return result
def generate_small_world_graph(self): max_edges = self.NODE_COUNT*(self.NODE_COUNT-1)/2 if self.EDGE_COUNT > max_edges: return complete_graph(self.NODE_COUNT) graph = Graph() graph.add_nodes_from(range(self.NODE_COUNT)) edges = performer.edge_indices.flatten() probabilities = performer.probabilities.flatten() for trial in range(len(edges)-9): edge_index = numpy.random.choice(edges, p=probabilities) source, destination = self.edge_nodes(edge_index) graph.add_edge(source, destination, length = self.link_length(source, destination), weight = self.edge_weight(source, destination)) probabilities[edge_index] = 0 probabilities /= sum(probabilities) if max(graph.degree().values()) > self.DEGREE_MAX: graph.remove_edge(source, destination) if graph.number_of_edges() > self.EDGE_COUNT: victim = random.choice(graph.edges()) graph.remove_edge(victim[0], victim[1]) if self.constraints_satisfied(graph): print 'performer.generate_small_world_graph:', print self.BENCHMARK, self.NODE_COUNT, self.EDGE_COUNT, trial self.process_graph(graph) return graph
def search_direct_relationships( graph: Graph, source: Optional[Dict] = None, edge: Optional[Dict] = None, target: Optional[Dict] = None) -> Iterable[Tuple]: """Search direct relation ship. Arguments: graph (Graph): graph instance source (Optional[Dict]): optional source node query constraint edge (Optional[Dict]): optional edge query constraint target (Optional[Dict]): optional target node query constraint Returns: (Iterable[Tuple]): itrable tuple of edge """ _iterable = search_edges(graph=graph, query=edge) if edge else graph.edges() if source: _predicate_source = prepare_query(source) _iterable = filter( lambda edge: _predicate_source(graph.nodes[edge[0]]), _iterable) if target: _predicate_target = prepare_query(target) _iterable = filter( lambda edge: _predicate_target(graph.nodes[edge[1]]), _iterable) return _iterable
def make_double(graph: nx.Graph): newgraph = nx.Graph() offset = graph.graph['max_id'] for u, v in graph.edges(): newgraph.add_edge(u, v + offset) newgraph.add_edge(v, u + offset) return newgraph
def get_edge_index(G: Graph) -> torch.LongTensor: """ Create pytorch geometric edge_index from a networkx graph. """ edge_index = toolz.functoolz.pipe(G.edges(), map(list), list, torch.LongTensor) return edge_index.t().contiguous()
def _edge_coords(g: nx.Graph, l: dict) -> dict: """Converts coordinates for the graph edges for plotting purposes. Args: g (nx.Graph): input graph l (dict[int, float]): Dictionary of nodes and their respective coordinates. Can be generated using a NetworkX `layout <https://networkx.github.io/documentation/latest/ reference/drawing.html#module-networkx.drawing.layout>`__ Returns: dict[str, list]: lists of x and y coordinates for the beginning and end of each edge. ``None`` is placed as a separator between pairs of nodes/edges. """ e_x = [] e_y = [] for e in g.edges(): start_x, start_y = l[e[0]] end_x, end_y = l[e[1]] e_x.append(start_x) e_x.append(end_x) e_y.append(start_y) e_y.append(end_y) e_x.append(None) e_y.append(None) return {"x": e_x, "y": e_y}
def __init__(self, binaryId: str, g: nx.Graph, label: int, node_tags: int = None, node_features=None): """ g: a networkx graph label: an integer graph label node_tags: a list of integer node tags node_features: a numpy array of continuous node features """ self.bId = binaryId self.num_nodes = len(node_tags) self.node_tags = node_tags self.label = None if label == '?' else label self.node_features = node_features # nparray (node_num * feature_dim) self.degs = list(dict(g.degree).values()) if g.number_of_edges() != 0: x, y = zip(*g.edges()) self.num_edges = len(x) self.edge_pairs = np.ndarray(shape=(self.num_edges, 2), dtype=np.int32) self.edge_pairs[:, 0] = x self.edge_pairs[:, 1] = y self.edge_pairs = self.edge_pairs.flatten() else: self.num_edges = 0 self.edge_pairs = np.array([]) log.warning(f'{binaryId} has no edge') log.debug(f'{binaryId} #nodes: {self.num_nodes}, label: {label}')
def make_prim_mst(G, generator=None): if generator is None: mst = Graph() else: mst = generator() #priorityQ is a list of list (the reverse of the edge tuple with the weight in the front) priorityQ = [] firstNode = G.nodes()[0] mst.add_node(firstNode) for edge in G.edges_iter(firstNode, data=True): if len(edge) != 3 or edge[2] is None: raise ValueError, "make_prim_mst accepts a weighted graph only (with numerical weights)" heappush(priorityQ, (edge[2], edge)) while len(mst.edges()) < (G.order() - 1): w, minEdge = heappop(priorityQ) if len(minEdge) != 3 or minEdge[2] is None: raise ValueError, "make_prim_mst accepts a weighted graph only (with numerical weights)" v1, v2, w = minEdge if v1 not in mst: for edge in G.edges_iter(v1, data=True): if edge == minEdge: continue heappush(priorityQ, (edge[2], edge)) elif v2 not in mst: for edge in G.edges_iter(v2, data=True): if edge == minEdge: continue heappush(priorityQ, (edge[2], edge)) else: # non-crossing edge continue mst.add_edge(minEdge[0], minEdge[1], minEdge[2]) return mst
def make_prim_mst(G, generator=None): if generator is None: mst = Graph() else: mst = generator() #priorityQ is a list of list (the reverse of the edge tuple with the weight in the front) priorityQ = [] firstNode = G.nodes()[0] mst.add_node(firstNode) for edge in G.edges_iter(firstNode, data=True): if len(edge) != 3 or edge[2] is None: raise ValueError, "make_prim_mst accepts a weighted graph only (with numerical weights)" heappush(priorityQ, (edge[2], edge)) while len(mst.edges()) < (G.order()-1): w, minEdge = heappop(priorityQ) if len(minEdge) != 3 or minEdge[2] is None: raise ValueError, "make_prim_mst accepts a weighted graph only (with numerical weights)" v1, v2, w = minEdge if v1 not in mst: for edge in G.edges_iter(v1, data=True): if edge == minEdge: continue heappush(priorityQ, (edge[2], edge)) elif v2 not in mst: for edge in G.edges_iter(v2, data=True): if edge == minEdge: continue heappush(priorityQ, (edge[2], edge)) else: # non-crossing edge continue mst.add_edge(minEdge[0],minEdge[1],minEdge[2]) return mst
def add_existing_knowledge_graph(self, another_graph: nx.Graph): """ Merge an existing knowledge graph into the current graph. """ self.add_nodes_from(another_graph.nodes(data=True)) self.add_edges_from(another_graph.edges(data=True)) return
def _assert_graph_and_graph_nx_equals(graph: tg.Graph, graph_nx: nx.Graph): # Check number of nodes and edges assert graph_nx.number_of_nodes() == graph.num_nodes assert graph_nx.number_of_edges() == graph.num_edges # Check node features assert has_node_features(graph) == has_node_features(graph_nx) if has_node_features(graph) and has_node_features(graph_nx): for node_features_nx, node_features in zip(graph_nx.nodes(data='features'), graph.node_features): torch.testing.assert_allclose(node_features_nx[1], node_features) # Check edge indexes for (sender_id_nx, receiver_id_nx, *_), sender_id, receiver_id in \ zip(graph_nx.edges, graph.senders, graph.receivers): assert sender_id_nx == sender_id assert receiver_id_nx == receiver_id assert has_edge_features(graph) == has_edge_features(graph_nx) if has_edge_features(graph) and has_edge_features(graph_nx): for (*_, edge_features_nx), edge_features in zip(graph_nx.edges(data='features'), graph.edge_features): torch.testing.assert_allclose(edge_features_nx, edge_features) # Check graph features assert has_global_features(graph) == has_global_features(graph_nx) if has_global_features(graph) and has_global_features(graph_nx): torch.testing.assert_allclose(graph_nx.graph['features'], graph.global_features)
def get_properties(network: nx.Graph): N = len(network) L = len(list(network.edges())) D = nx.density(network) d = nx.diameter(network) C = nx.average_clustering(network, weight="weight") return N, L, D, d, C
def test_happy_path(self): graph = Graph() initial_node = gen_name() graph.add_node(initial_node, layer=0, position=(0.5, 0.5), label='E') if visualize_tests: visualize_graph_3d(graph) pyplot.show() P1().apply(graph, [initial_node]) nodes_data = graph.nodes(data=True) self.assertEqual(len(graph.nodes()), 7) self.assertEqual(len(graph.edges()), 13) # check the initial node initial_node_data = nodes_data[initial_node] self.assertEqual(initial_node_data['layer'], 0) self.assertEqual(initial_node_data['position'], (0.5, 0.5)) self.assertEqual(initial_node_data['label'], 'e') # check other nodes vx_bl = get_node_at(graph, 1, (0, 0)) vx_br = get_node_at(graph, 1, (1, 0)) vx_tl = get_node_at(graph, 1, (0, 1)) vx_tr = get_node_at(graph, 1, (1, 1)) self.assertIsNotNone(vx_bl) self.assertIsNotNone(vx_br) self.assertIsNotNone(vx_tl) self.assertIsNotNone(vx_tr) self.assertEqual(nodes_data[vx_bl]['label'], 'E') self.assertEqual(nodes_data[vx_br]['label'], 'E') self.assertEqual(nodes_data[vx_tl]['label'], 'E') self.assertEqual(nodes_data[vx_tr]['label'], 'E') vx_i1 = get_node_at(graph, 1, (2 / 3, 1 / 3)) vx_i2 = get_node_at(graph, 1, (1 / 3, 2 / 3)) self.assertIsNotNone(vx_i1) self.assertIsNotNone(vx_i2) self.assertEqual(nodes_data[vx_i1]['label'], 'I') self.assertEqual(nodes_data[vx_i2]['label'], 'I') self.assertTrue(graph.has_edge(initial_node, vx_i1)) self.assertTrue(graph.has_edge(initial_node, vx_i2)) self.assertTrue(graph.has_edge(vx_tl, vx_tr)) self.assertTrue(graph.has_edge(vx_tr, vx_br)) self.assertTrue(graph.has_edge(vx_br, vx_bl)) self.assertTrue(graph.has_edge(vx_bl, vx_tl)) self.assertTrue(graph.has_edge(vx_bl, vx_tr)) self.assertTrue(graph.has_edge(vx_i1, vx_bl)) self.assertTrue(graph.has_edge(vx_i1, vx_br)) self.assertTrue(graph.has_edge(vx_i1, vx_tr)) self.assertTrue(graph.has_edge(vx_i2, vx_bl)) self.assertTrue(graph.has_edge(vx_i2, vx_tl)) self.assertTrue(graph.has_edge(vx_i2, vx_tr)) if visualize_tests: visualize_graph_3d(graph) pyplot.show()
def summarize_email(raw_text, sender=None, language='english'): raw_text = strip_signature(raw_text, sender) stopwords = cachedStopWords sentence_list = tokenize.sent_tokenize(raw_text, language) word_set = [get_tokenized(sentence, stopwords) for sentence in sentence_list] graph = Graph() pairs = itertools.combinations(enumerate(filter(None, word_set)), 2) for (index_a, words_a), (index_b, words_b) in pairs: similarity = cosine(words_a, words_b) if similarity > 0: graph.add_edge(index_a, index_b, weight=similarity) if not graph.edges(): return sentence_list[0] ranked_sentence_indexes = pagerank(graph).items() sentences_by_rank = sorted(ranked_sentence_indexes, key=itemgetter(1), reverse=True) summary_size = int(math.ceil(len(sentence_list) / 3)) best_sentences = map(itemgetter(0), sentences_by_rank[:summary_size]) best_sentences_in_order = sorted(best_sentences) return ' '.join(sentence_list[index] for index in best_sentences_in_order)
def getGraphInfo(self, model, geneList): #get undirected graph undirected = self.to_undirected() #calculate 5th percentile weight sort = list() for edge in self.edges(data=True): sort.append(edge[2]['weight']) sort.sort() fifth = sort[int(math.ceil(len(sort))*0.05-1)] genes = self.geneToNode.keys() geneTuples = set() for gene in genes: geneTuples.add((gene,'')) geneTuples.add((gene,"NOT")) subTerms = set() test = Graph() length = 0 copyGraph = self.createDiGraphCopy(geneTuples) subTerms = set() for gene in list(geneList): subTerms.update(self.getNodesByGene(gene)) undirected = self.augmentGraph(undirected, list(subTerms), geneTuples, fifth) test = make_steiner_tree(undirected, list(subTerms)) length = 0 for subEdge in test.edges(): length += test.edge[subEdge[0]][subEdge[1]]['weight'] prob = calcProb(length, len(geneList), model) return prob, test
def sample_edges_ic(graph: nx.Graph, seed_set: Sequence[NxDocumentNode]) -> Sequence[NxDocumentNode]: """ Samples every edge in the graph with the probability = similarity. Args: graph: The graph on which we should operate. seed_set: A set of nodes which are 'active' at the beginning. Returns: The set of reachable nodes given the seed set and the edges we sampled. """ sampled = nx.Graph(graph) sampled.remove_edges_from(sampled.edges()) for from_node, to_node, data in graph.edges(data=True): if random.random() <= data['similarity']: # Note: Batching this (i.e. only add all sampled at once) actually # slows things down under NetworkX... sampled.add_edge(from_node, to_node) all_reached = DefaultReachability().compute_reachability(sampled, seed_set) return all_reached
def read_graph(path): # Error object to be used if parsing fails error = IOError("Format of file %s is illegal" % path) with open(path) as graph_file: g = Graph() # Read the first line for number of nodes and number of edges nv, ne = read_line(graph_file.readline()) # Traverse all lines for line in graph_file.readlines(): n1, n2 = read_line(line) # Check whether the nodes are in a legal range if (n1 > nv or n1 < 1 or n2 > nv or n2 < 1): raise error g.add_edge(n1, n2) # Check the number of edges is correct if len(g.edges()) != ne: raise error return g
from networkx import Graph entries = Graph() #entries.add_node('@davidmartinb') #entries.add_node('@emartinborregon') entries.add_edge('@davidmartinb','@emartinborregon') #entries.add entries2 = entries.copy() #entries.add_node('@davidmartinb') #entries.add_node('@emartinborregon') entries2.add_edge('@davidmartinb','@test') entries.add_edge('@davidmartinb','@emartinborregon') #entries.add print set(entries2.nodes())-set(entries.nodes()) edges1=entries.edges() entries2.remove_edges_from( edges1 ) print entries2.edges()
ips = {} # filter all relays in this consensus to those that # have a descriptor, are running, and are fast for relay in consensus.relays: if (relay in descriptors): sd = descriptors[relay] # server descriptor rse = consensus.relays[relay] # router status entry if "Running" in rse.flags and "Fast" in rse.flags: if relay not in ips: ips[relay] = [] ips[relay].append(sd.address) # build edges between every relay that could have been # selected in a path together for r1 in ips: for r2 in ips: if r1 is r2: continue g.add_edges_from(product(ips[r1], ips[r2])) nsf_i += 1 # check if we should do a checkpoint and save our progress if nsf_i == nsf_len or "01-00-00-00" in fname: chkpntstart = fname[0:10] with open("relaypairs.{0}--{1}.json".format(chkpntstart, chkpntend), 'wb') as f: json.dump(g.edges(), f) print "" print('Num addresses: {0}'.format(g.number_of_nodes())) print('Num unique pairs: {0}'.format(g.number_of_edges())) # write final graph to disk with open(out_file, 'wb') as f: json.dump(g.edges(), f) ##########
degreeMap = nx.degree(random_bipartite_graph) sortedval = sorted(degreeMap.items(),key = lambda x : x[1],reverse=True) for val in range(10): if val == 5: for node_value in range(min_value_x+10): node = random_bipartite_graph.nodes()[node_value] if not node_value in corrupted_node: corrupted_node[node_value] = {} corrupted_node[node_value]['old'] = degreeMap[node_value] compare_val = min_value + 0.9*(max_value - min_value) for node_val in range(min_value,int(compare_val)): edgeArr = random_bipartite_graph.edges() if not (node,node_val) in edgeArr: random_bipartite_graph.add_edge(node,node_val) pageRankMap = nx.pagerank(random_bipartite_graph) for i in pageRankMap: if i not in pageRankNodeMap: pageRankNodeMap[i] = [] x = Decimal(pageRankMap[i]).quantize(Decimal('0.000000001')) pageRankNodeMap[i].append(float(x)) degreeMap = nx.degree(random_bipartite_graph) for el in corrupted_node:
class Topo(object): '''Data center network representation for structured multi-trees.''' def __init__(self): '''Create Topo object. ''' self.g = Graph() self.node_info = {} # dpids hash to Node objects self.edge_info = {} # (src_dpid, dst_dpid) tuples hash to Edge objects self.ports = {} # ports[src][dst] is port on src that connects to dst self.id_gen = NodeID # class used to generate dpid def add_node(self, dpid, node): '''Add Node to graph. @param dpid dpid @param node Node object ''' self.g.add_node(dpid) self.node_info[dpid] = node def add_edge(self, src, dst, edge = None): '''Add edge (Node, Node) to graph. @param src src dpid @param dst dst dpid @param edge Edge object ''' src, dst = tuple(sorted([src, dst])) self.g.add_edge(src, dst) if not edge: edge = Edge() self.edge_info[(src, dst)] = edge self.add_port(src, dst) def add_port(self, src, dst): '''Generate port mapping for new edge. @param src source switch DPID @param dst destination switch DPID ''' src_base = SWITCH_PORT_BASE if self.is_switch(src) else 0 dst_base = SWITCH_PORT_BASE if self.is_switch(dst) else 0 if src not in self.ports: self.ports[src] = {} if dst not in self.ports[src]: # num outlinks self.ports[src][dst] = len(self.ports[src]) + src_base if dst not in self.ports: self.ports[dst] = {} if src not in self.ports[dst]: # num outlinks self.ports[dst][src] = len(self.ports[dst]) + dst_base def node_enabled(self, dpid): '''Is node connected, admin on, powered on, and fault-free? @param dpid dpid @return bool node is enabled ''' ni = self.node_info[dpid] return ni.connected and ni.admin_on and ni.power_on and not ni.fault def nodes_enabled(self, dpids, enabled = True): '''Return subset of enabled nodes @param dpids list of dpids @param enabled only return enabled nodes? @return dpids filtered list of dpids ''' if enabled: return [n for n in dpids if self.node_enabled(n)] else: return dpids def nodes(self, enabled = True): '''Return graph nodes. @param enabled only return enabled nodes? @return dpids list of dpids ''' return self.nodes_enabled(self.g.nodes(), enabled) def nodes_str(self, dpids): '''Return string of custom-encoded nodes. @param dpids list of dpids @return str string ''' return [str(self.id_gen(dpid = dpid)) for dpid in dpids] def is_switch(self, n): '''Returns true if node is a switch.''' return self.node_info[n].is_switch def switches(self, enabled = True): '''Return switches. @param enabled only return enabled nodes? @return dpids list of dpids ''' nodes = [n for n in self.g.nodes() if self.is_switch(n)] return self.nodes_enabled(nodes, enabled) def hosts(self, enabled = True): '''Return hosts. @param enabled only return enabled nodes? @return dpids list of dpids ''' def is_host(n): '''Returns true if node is a host.''' return not self.node_info[n].is_switch nodes = [n for n in self.g.nodes() if is_host(n)] return self.nodes_enabled(nodes, enabled) def edge_enabled(self, edge): '''Is edge admin on, powered on, and fault-free? @param edge (src, dst) dpid tuple @return bool edge is enabled ''' src, dst = edge src, dst = tuple(sorted([src, dst])) ei = self.edge_info[tuple(sorted([src, dst]))] return ei.admin_on and ei.power_on and not ei.fault def edges_enabled(self, edges, enabled = True): '''Return subset of enabled edges @param edges list of edges @param enabled only return enabled edges? @return edges filtered list of edges ''' if enabled: return [e for e in edges if self.edge_enabled(e)] else: return edges def edges(self, enabled = True): '''Return edges. @param enabled only return enabled edges? @return edges list of dpid pairs ''' return self.edges_enabled(self.g.edges(), enabled) def edges_str(self, dpid_pairs): '''Return string of custom-encoded node pairs. @param dpid_pairs list of dpid pairs (src, dst) @return str string ''' edges = [] for pair in dpid_pairs: src, dst = pair src = str(self.id_gen(dpid = src)) dst = str(self.id_gen(dpid = dst)) edges.append((src, dst)) return edges def port(self, src, dst): '''Get port number. @param src source switch DPID @param dst destination switch DPID @return tuple (src_port, dst_port): src_port: port on source switch leading to the destination switch dst_port: port on destination switch leading to the source switch ''' if src in self.ports and dst in self.ports[src]: assert dst in self.ports and src in self.ports[dst] return (self.ports[src][dst], self.ports[dst][src]) def enable_edges(self): '''Enable all edges in the network graph. Set admin on, power on, and fault off. ''' for e in self.g.edges(): src, dst = e ei = self.edge_info[tuple(sorted([src, dst]))] ei.admin_on = True ei.power_on = True ei.fault = False def enable_nodes(self): '''Enable all nodes in the network graph. Set connected on, admin on, power on, and fault off. ''' for node in self.g.nodes(): ni = self.node_info[node] ni.connected = True ni.admin_on = True ni.power_on = True ni.fault = False def enable_all(self): '''Enable all nodes and edges in the network graph.''' self.enable_nodes() self.enable_edges() def name(self, dpid): '''Get string name of node ID. @param dpid DPID of host or switch @return name_str string name with no dashes ''' return self.id_gen(dpid = dpid).name_str() def ip(self, dpid): '''Get IP dotted-decimal string of node ID. @param dpid DPID of host or switch @return ip_str ''' return self.id_gen(dpid = dpid).ip_str()
def multigraph_to_graph(g: MultiGraph) -> Graph: gx = Graph() gt = Graph(g) gx.add_nodes_from(gt.nodes()) gx.add_edges_from(gt.edges()) return gx
class SocialNetwork(object): """Object oriented interface for conducting social network analysis.""" valid_indexes = [] for index_name in conf.INDEXES.keys(): valid_indexes.append(index_name) cache = None def __init__(self): logging.info("libSNA object created.") self.graph = Graph() self.measures = {} self.nodesmeasures = {} self.edgesmeasures = {} for index in self.valid_indexes: self.measures[index] = None def getNodes(self): nodes = self.graph.nodes() nodes.sort() return nodes def getEdges(self): edges = self.graph.edges() return edges def loadGraph(self, nodes, edges): logging.info("Loading network from input variables") for node in nodes: self.graph.add_node(node) for edge in edges: self.graph.add_edge(edge[0], edge[1]) self.graph.name = "Social Network" logging.info("Finished loading network.") def runMeasure(self, measure_name, backend): if measure_name in self.valid_indexes: eval('self.calculate_' + measure_name.replace(' ', '_') + '(backend)') else: logging.error("Unable to calculate the measure (%s)"%(measure_name)) def returnResults(self, measure_name, value = 'value'): if measure_name in self.valid_indexes: if value == 'value': return self.measures[measure_name] elif value == 'nodes': return self.nodesmeasures[measure_name] elif value == 'edges': return self.edgesmeasures[measure_name] else: return None def displayResults(self, measure_name, value = 'value'): if measure_name in self.valid_indexes: if value == 'value': logging.info((conf.INDEX_TYPES[measure_name] + '.') % self.measures[measure_name]) elif value == 'nodes': logging.info(str(self.nodesmeasures[measure_name] or '<null>')) elif value == 'edges': logging.info(str(self.edgesmeasures[measure_name] or '<null>')) else: logging.error("Unable to calculate the measure (%s)"%(measure_name)) def calculateMeasures(self, backend=False): for measure_name in self.valid_indexes: self.runMeasure(measure_name, backend=False) def calculate_density(self, backend=False): logging.info("Calculating density.") nodes = self.graph.nodes() edges = self.graph.edges() tot_edges = float(len(nodes) * (len(nodes)-1)) tot_edges = tot_edges / 2 num_edges = float(len(edges)) w = {} for n1 in nodes: for n2 in nodes: w[n1,n2] = 0.0 for n1,n2 in edges: w[n1,n2] = 1.0 self.measures['density'] = num_edges / tot_edges * 100 self.nodesmeasures['density'] = None self.edgesmeasures['density'] = w def calculate_geodesic(self, backend=False): logging.info("Calculating geodesic.") path = self.floyd_warshall(backend) nodes = self.graph.nodes() dividend = 0 geodesic = float(0) geodesic_edges = {} for i in nodes: for j in nodes: try: geodesic_edges[i,j] = path[i,j] geodesic += path[i,j] dividend += 1 except KeyError: pass geodesic /= dividend self.measures['geodesic'] = geodesic self.nodesmeasures['geodesic'] = None self.edgesmeasures['geodesic'] = geodesic_edges def calculate_fragmentation(self, backend=False): logging.info("Calculating fragmentation.") nodes = self.graph.nodes() w = self.floyd_warshall(backend) fragmentation = float(0) for i in nodes: for j in nodes: try: w[i,j] except KeyError: fragmentation += 1 pass fragmentation /= len(nodes)*(len(nodes)-1) self.measures['fragmentation'] = fragmentation * 100 self.nodesmeasures['fragmentation'] = None self.edgesmeasures['fragmentation'] = w def calculate_diameter(self, backend=False): logging.info("Calculating diameter.") path = self.floyd_warshall(backend) nodes = self.graph.nodes() diameter = float(0) for i in nodes: for j in nodes: try: diameter = max(diameter, path[i,j]) except KeyError: pass self.measures['diameter'] = diameter self.nodesmeasures['diameter'] = None self.edgesmeasures['diameter'] = path def calculate_degree(self, backend=False): logging.info("Calculating degree.") degrees = degree_centrality(self.graph) degree = float(sum(degrees.values())/len(degrees.values())) self.measures['degree'] = degree * 100 self.nodesmeasures['degree'] = degrees self.edgesmeasures['degree'] = None def calculate_centralization(self, backend=False): logging.info("Calculating centralization.") degrees = degree_centrality(self.graph) centralization = float(0) maxdegree = max(degrees.values()) for degree in degrees.values(): centralization += maxdegree-degree centralization /= len(degrees.values())-1 self.measures['centralization'] = centralization * 100 self.nodesmeasures['centralization'] = degrees self.edgesmeasures['centralization'] = None def calculate_closeness(self, backend=False): logging.info("Calculating closeness.") closenesses = closeness_centrality(self.graph) closeness = float(sum(closenesses.values())/len(closenesses.values())) self.measures['closeness'] = closeness * 100 self.nodesmeasures['closeness'] = closenesses self.edgesmeasures['closeness'] = None def calculate_eigenvector(self, backend=False): logging.info("Calculating eigenvector.") eigenvectors = eigenvector_centrality(self.graph) eigenvector = float(sum(eigenvectors.values())/len(eigenvectors.values())) self.measures['eigenvector'] = eigenvector * 100 self.nodesmeasures['eigenvector'] = eigenvectors self.edgesmeasures['eigenvector'] = None def calculate_betweenness(self, backend=False): logging.info("Calculating betweenness.") betweennesses = betweenness_centrality(self.graph) betweenness = float(sum(betweennesses.values())/len(betweennesses.values())) self.measures['betweenness'] = betweenness * 100 self.nodesmeasures['betweenness'] = betweennesses self.edgesmeasures['betweenness'] = None def calculate_cliques(self, backend=False): logging.info("Calculating cliques.") cliques = list(find_cliques(self.graph)) w = {} nodes = self.graph.nodes() for node in nodes: w[node] = 0.0 for clique in cliques: if node in clique: w[node] += 1 self.measures['cliques'] = len(cliques) self.nodesmeasures['cliques'] = w self.edgesmeasures['cliques'] = None def calculate_comembership(self, backend=False): logging.info("Calculating comembership.") nodes = self.graph.nodes() n = len(nodes) if not backend and n > 500: raise network_big.NetworkTooBigException(n) cliques = list(find_cliques(self.graph)) w = {} for clique in cliques: for node1 in clique: for node2 in clique: try: w[node1,node2] += 1 except KeyError: w[node1,node2] = 1 nodes = w.keys() comembership = float(0) for node1, node2 in nodes: if node1 != node2: comembership += w[node1,node2] num_nodes = len(self.graph.nodes()) comembership /= num_nodes*(num_nodes-1) self.measures['comembership'] = comembership self.nodesmeasures['comembership'] = None self.edgesmeasures['comembership'] = w def calculate_components(self, backend=False): logging.info("Calculating components.") components = nx.connected_component_subgraphs(self.graph) w = {} nodes = self.graph.nodes() for node in nodes: w[node] = 0.0 for component in components: if len(component) > 1: for node in component: w[node] += 1 self.measures['components'] = len(components) self.nodesmeasures['components'] = w self.edgesmeasures['components'] = None def floyd_warshall(self, backend): nodes = self.graph.nodes() if not backend and len(nodes) > 400: raise network_big.NetworkTooBigException(len(nodes)) logging.info("Computing Floyd-Warshall.") infvalue = 127 #sys.maxint F = nx.floyd_warshall_numpy(self.graph, dtype=np.int8, infvalue=infvalue) w = {} for i in range(0, len(nodes)): for j in range(0, len(nodes)): if not F[i,j] == infvalue: w[nodes[i],nodes[j]] = F[i,j] return w
class WishPool: def __init__( self, wishes, min_edge_score = MIN_EDGE_SCORE, # min_number_of_edges = MIN_NUMBER_OF_EDGES, connector = default_connector ): """ A filterable pool of wishes represented as nodes. Is used to find relations between wishes. @param connector: default connector is jaccard @return: """ self.graph = Graph() self.min_edge_weight = min_edge_score # self.min_number_of_edges = min_number_of_edges for wish in wishes: self.graph.add_node( wish ) # loops through the existing nodes in the graph for other in self.graph.nodes_iter(): # compares candidate to all existing nodes except itself if other != wish and other.person != wish.person: score = connector( wish, other ) if score > self.min_edge_weight: self.graph.add_edge( wish, other, weight=score ) ## processes the graph, excludes lonely nodes self.connected_nodes = self.update_connected_nodes() debug_graph(self.graph, message="Connected nodes are set") self.lonely_nodes = self.update_lonely_nodes() self.update_cliques() ## evaluates alternatives, gathers suggestions for each wish # this implies that some cliques occur twice self.suggestions = self.update_suggestions() def update_connected_nodes( self ): connected = set() for n in self.graph.edges(): connected.add( n[0] ) return connected def update_lonely_nodes( self ): whole_graph = set( self.graph.nodes() ) return whole_graph.difference( self.connected_nodes ) def remove_lonely_nodes( self ): raise NotImplementedError def update_cliques( self ): result = set() for c in find_cliques( self.graph ): if len(c) > 1: result.add( Clique(c) ) self.cliques = result return result def get_distributed_cliques( self ): self.cliques_for_wish = {} for n in self.graph.nodes(): clique_buffer = [] for c in self.cliques: if n in c.nodes: clique_buffer.append( c ) if len(clique_buffer): self.cliques_for_wish[n.pk] = [ c for c in clique_buffer if len(c.nodes) > 1 ] return self.cliques_for_wish def get_conflicting_cliques( self ): result = {} for w,c in self.get_distributed_cliques(): if len(c) > 1: result[w] = c return result def update_suggestions( self ): suggestions = [] for wish_pk, cliques in self.get_distributed_cliques().items(): suggestion = Suggestion( Wish.objects.get(pk=wish_pk), cliques ) suggestions.append( suggestion ) self.suggestions = suggestions return suggestions def create_groups( self ): distinct_cliques = set() for s in self.suggestions: distinct_cliques.add( s.get_best_clique() ) for c in distinct_cliques: c.create_group() def get_suggestion_pool( self ): return SuggestionPool( self.suggestions )
def mergeAugmented(self, model, maxProb=0.05, maxMergedGeneCount=200, minGeneAutoMerge=5, minLevel=0): #get undirected graph undirected = self.to_undirected() #calculate descendant dictionary descendantDict = dict() sortedNodes = topological_sort(self) sortedNodes.reverse() for node in sortedNodes: descendants = descendantDict.get(node, set()) descendants.add(node) descendantDict[node] = descendants for parent in self.predecessors(node): if parent not in descendantDict: descendantDict[parent] = set(descendants) else: descendantDict[parent].update(descendants) #calculate 5th percentile weight sort = list() for edge in self.edges(data=True): sort.append(edge[2]['weight']) sort.sort() fifth = sort[int(math.ceil(len(sort))*0.05-1)] genes = self.geneToNode.keys() geneTuples = set() for gene in genes: geneTuples.add((gene,'')) geneTuples.add((gene,"NOT")) subTerms = set() test = Graph() length = 0 copyGraph = self.createDiGraphCopy(geneTuples) queue = [] leafs = set() for node in self.nodes(): if len(self.edges(node)) == 0: leafs.add(node) for parent in self.predecessors(node): heappush(queue, (self.edge[parent][node]['weight'], (parent, node))) while len(queue) > 0: edge = heappop(queue) loss = copyGraph.node[edge[1][0]]['infoLoss'] + edge[0] + copyGraph.node[edge[1][1]]['infoLoss'] mergedNodes = copyGraph.node[edge[1][0]]['mergeCount'] + 1 + copyGraph.node[edge[1][1]]['mergeCount'] mergedGenes = len(copyGraph.node[edge[1][0]]['mergeGene'].union(copyGraph.node[edge[1][1]]['mergeGene']).union(copyGraph.node[edge[1][1]]['gene']).union(copyGraph.node[edge[1][0]]['gene'])) genesCount = len(copyGraph.node[edge[1][1]]['mergeGene'].union(copyGraph.node[edge[1][1]]['gene'])) if mergedGenes <= maxMergedGeneCount and self.getLevel(edge[1][0]) >= minLevel: subNodes = descendantDict[edge[1][0]] subGraph = undirected.subgraph(subNodes.intersection(self.nodes())).copy() subRootGeneTuples = copyGraph.node[edge[1][0]]['mergeGene'].union(copyGraph.node[edge[1][1]]['mergeGene']).union(copyGraph.node[edge[1][1]]['gene']).union(copyGraph.node[edge[1][0]]['gene']).intersection(geneTuples) subRootGenes = set() for geneGroup in list(subRootGeneTuples): subRootGenes.add(geneGroup[0]) subTerms = set() for gene in list(subRootGenes): subTerms.update(self.getNodesByGene(gene)) subTerms.intersection_update(subGraph.nodes()) subGraph = self.augmentGraph(subGraph, list(subTerms), geneTuples, fifth) test = make_steiner_tree(subGraph, list(subTerms)) length = 0 for subEdge in test.edges(): length += test.edge[subEdge[0]][subEdge[1]]['weight'] prob = calcProb(length, mergedGenes, model) else: prob = 1 + maxProb if prob < maxProb or genesCount <= minGeneAutoMerge: parent = edge[1][0] predecessors = copyGraph.predecessors(edge[1][1]) copyGraph.node[edge[1][0]]['mergeGene'].update(copyGraph.node[edge[1][1]]['mergeGene']) copyGraph.node[edge[1][0]]['mergeGene'].update(copyGraph.node[edge[1][1]]['gene']) copyGraph.node[edge[1][0]]['mergePMID'].update(copyGraph.node[edge[1][1]]['mergeGene']) copyGraph.node[edge[1][0]]['mergePMID'].update(copyGraph.node[edge[1][1]]['pmid']) copyGraph.remove_edge(edge[1][0], edge[1][1]) copyGraph.remove_node(edge[1][1]) for pred in predecessors: if len(copyGraph.edges(pred)) == 0: copyGraph = self.delCopyGraphEmptyNode(copyGraph, pred) copyGraph.node[parent]['infoLoss'] = length copyGraph.node[parent]['mergeCount'] = mergedNodes queue = [] leafs = set() for node in copyGraph.nodes(): if len(copyGraph.edges(node)) == 0: leafs.add(node) for parent in copyGraph.predecessors(node): heappush(queue, (copyGraph.edge[parent][node]['weight'], (parent, node))) nodes = self.nodes() for node in nodes: if node not in copyGraph: self.remove_node(node) else: self.node[node]['data'].addMergedGenes(copyGraph.node[node]['mergeGene']) self.node[node]['data'].setInfoLoss(copyGraph.node[node]['infoLoss']) self.node[node]['data'].setMergedCount(copyGraph.node[node]['mergeCount']) self.node[node]['data'].setMergedPMIDs(copyGraph.node[node]['mergePMID']) return self, leafs, copyGraph
class Network(HasTraits): """ The implementation of the Connectome Networks """ implements(INetwork) # Network ID, from parsed GraphML the graphid networkid = '' # Network name networkname = Str # network name as seen in the TreeView name = Str # Is it an hierarchical network? hierarchical = CBool(False) # TODO: later, also Hypergraph?! # see: http://www.ploscompbiol.org/article/info%3Adoi%2F10.1371%2Fjournal.pcbi.1000385 hypergraph = CBool(False) # Directionality of the Network, {True: 'directed', False: 'undirected'} directed = CBool(False) # metadata for the network metadata = Dict # NodeKeys from the parsed GraphML # These are Dict of Dict, all having strings nodekeys = {} # Edgekeys, from parsed GraphML edgekeys = {} # A NetworkX AttrGraph containing all the information graph = Any # Surface containers surfaces = List(ISurfaceContainer) # Surface containers loaded surfaces_loaded = List(ISurfaceContainer) # Volume data volumes = List(IVolume) # Track data tracks = List(ITrackfile) # is this network active, and thus a render manager displayed? active = Bool # the render manager of this network rendermanager = Instance(RenderManager) # DatasourceManager Instance of this network datasourcemanager = Instance(DatasourceManager) # private traits ########### # parent cfile this networks belongs to _parentcfile = Any # filezip of cfile _filezip = DelegatesTo('_parentcfile') # edge parameters for visualization _edge_para = Instance(EdgeParameters) # View traits_view = View( Item('networkname', style = 'readonly'), Item('hierarchical', style = 'simple'), Item('hypergraph', style = 'simple'), Item('directed', style = 'simple'), Item('active', style = 'simple'), title = 'A network', ) def __init__(self, name, src = None, directed = '0', pickled_graph = None, \ hierarchical ='0', hypergraph = '0', graph = None): """ Initializes the network and sets the traits. Parameters ---------- name : string the name of the network src : file handle or StringIO object the source text of the network to parse pickled_graph : NetworkX graph reference to a graph object, src should be None directed : bool Is the network directed? hierarchical : bool Is the network hierarchical? (default: '0') Not implemented yet. hypergraph : bool Is the network a hypergraph? (default: '0') Not implemented yet. """ # initialize the traits self.networkname = name self.directed = int(directed) self.hierarchical = int(hierarchical) self.hypergraph = int(hypergraph) if src is None and not pickled_graph is None: self.load_pickled_graphml(pickled_graph) else: if not src is None: # generates NetworkX Graph self.graph = self.parse_network_graphml(src) elif not graph is None: self.graph = graph else: if self.directed: from networkx import DiGraph self.graph = DiGraph() logger.info("Initialize with empty directed Graph") else: from networkx import Graph self.graph = Graph() logger.info("Initialize with empty undirected Graph") # initializes the weight key of the graph # with the first edgekey if len(self.edgekeys) > 0: edgk = self.edgekeys.keys() if not 'weight' in edgk: self.set_weight_key(edgk[0]) else: # try grabbing first edge from the graph if self.graph.number_of_edges() > 0: it = self.graph.edges_iter(data=True) edg = it.next() if len(edg[2]) > 0: # if it has a weigth key, just leave it edgk = edg[2].keys() if not 'weight' in edgk: self.set_weight_key(edgk[0]) else: pass # logger.error('Cannot set weight key for network : ' + self.networkname) def _name_default(self): return self.networkname def _active_default(self): return False def _active_changed(self , value): if value: n = self.name if ' [Active]' not in n: self.name = "%s [Active]" % n # XXX: do refactor with threaded loading of surfaces # and default spring force layout for graph rendering! # see also TraitsUI Demos: Multi thread demo # load the surface containers data # make a deep copy of the already loaded surface containers import copy self.surfaces = copy.deepcopy(self.surfaces_loaded) for surfcont in self.surfaces: surfcont.load_surface_container() if self.rendermanager is None: self._create_datasourcemanager() self._create_renderer() # if there are no surfaces, initialize # network rendering, but only if dn_positions are given if len(self.surfaces) == 0: logger.debug('No surfaces found. Try to render graph view with dn_position information.') self.rendermanager.datasourcemanager._compute_3DLayout(-1, -1) self.rendermanager.visualize_graph() else: logger.debug('SurfaceContainer found. Try to render 3D View using %s.' % self.surfaces[0].name) if len(self.surfaces[0].surfaces) == 0: logger.debug('Rendering not possible because SurfaceContainer contains no surfaces.') else: logger.debug('Using first surface for rendering.') self.surfaces[0].surfaces[0]._layout_3DView() if not self._parentcfile._workbenchwin is None: #from enthought.pyface.timer.api import do_later from enthought.pyface.api import GUI GUI.invoke_later(self._parentcfile._workbenchwin.status_bar_manager.set, message = '') else: self.name = self.name.replace(' [Active]', '') logger.debug('Close RenderManager scenes') self.rendermanager.close_scenes() logger.debug('All scenes closed.') # FIXME: what is happening in the following? # e.g. for instances. e.g. reset traits? # XXX: this is somehow not correct. do i need to use del # or remove/reset traits? self.rendermanager = None self.datasourcemanager = None self.surfaces = [] def _de_activate(self): """ Toggles the internal state of the activation """ if self.active: self.active = False else: self._parentcfile._workbenchwin.status_bar_manager.message = 'Activating network ...' self.active = True def _edge_parameters(self): """ Dialog to change edge attribute and thresholding """ if self._edge_para is None: self._edge_para = EdgeParameters(self, self.rendermanager.attract.point_scalars_name) self._edge_para.configure_traits() def _create_renderer(self): """ Creates the renderer instance if not yet available and opens the scenes in mayavi """ if self.active: if self.rendermanager is None: logger.debug('Create a RenderManager instance') self.rendermanager = RenderManager(network=self) else: logger.debug('RenderManager instance already running. This is an error.') def _create_datasourcemanager(self): """ Creates the datasource manager instance if not yet available """ if self.active: if self.datasourcemanager is None: logger.debug('Create a DatasourceManager instance') self.datasourcemanager = DatasourceManager(network=self) else: logger.debug('DatasourceManager instance already running. This is an error.') def _render_matrix(self): """ Invokes the connectivity matrix viewer """ # assume the network is activated (i.e. data source generated) # we need the edge parameter instance initialized if self._edge_para is None: self._edge_para = EdgeParameters(self, self.rendermanager.attract.point_scalars_name) logger.debug('Invoke Matrix Viewer...') self.rendermanager.invoke_matrix_viewer() def _trackvis_launch(self): """ Generates scene file and launch Trackvis on the selected nodes """ import tempfile logger.debug('Starting TrackVis ...') # extract selected subgraph selectionlist = self.get_selectiongraph_list() if len(selectionlist) == 0: # message from enthought.traits.ui.message import message message(message = 'No nodes selected for ROI creation!', title = 'Infomessage', buttons = [ 'OK' ], parent = None) tmpgraph = self.graph.subgraph(selectionlist) # extract trackfile temporarily if len(self.tracks) == 0: logger.info('No trackfile found to invoke Trackvis.') return else: # load the first trackfile trackfname = self.tracks[0].load_trackfile_to_file() # find the first valid segmentation volume in the self.volumes list for vol in self.volumes: if vol.segmentation: logger.debug('Found a segmentation volume file. Assume labels are corresponding.') volumefname = vol.load_volume_to_file() break # generate the scene file in the temporary folder tmpscenefile=tempfile.mkstemp(prefix='tmp', suffix='.scene') # generate trackfile generate_scene_file(scenefname=tmpscenefile[1], \ trackfname = trackfname, \ volumefname = volumefname, \ selectiongraph = tmpgraph) # execute trackvis in a thread pref = preference_manager.preferences action = ThreadedTrackvis(tvpath = pref.get('cviewer.plugins.ui.trackvispath'), \ fname = tmpscenefile[1], \ trkfname = trackfname,\ volfname = volumefname) action.start() def add_surface_container(self, surfacecontainer): """ Add a surface container to the loaded list Parameters ---------- surfacecontainer : `ISurfaceContainer` instance a surface container object """ surfacecontainer._networkref = self self.surfaces_loaded.append(surfacecontainer) def add_volume(self, volume): """ Adds a volume to the volumes list Parameters ---------- volume : `IVolume` instance a volume object """ self.volumes.append(volume) def add_trackfile(self, trackfile): """ Adds a trackfile to the tracks list Parameters ---------- trackfile : `ITrackfile` instance a trackfile of type ITrackfile """ self.tracks.append(trackfile) def unselect_all(self): """ Unselects every node in the current network """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') from numpy import array # get all the nodes graphnodes = self.datasourcemanager._srcobj.relabled_graph.nodes() # and unselect all nodes self.rendermanager._select_nodes(selection_node_array = array(graphnodes)) def select_all(self): """ Selects all nodes in the current network """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') from numpy import array # get all the nodes graphnodes = self.datasourcemanager._srcobj.relabled_graph.nodes() # and select all nodes self.rendermanager._select_nodes(selection_node_array = array(graphnodes), activate = True) def set_selectiongraph(self, sellist, activate = False): """ Sets the selected nodes in the network to active. Parameters ---------- sellist : array_like a list of nodeids conforming to the NetworkX node id activate : boolean set the selectionlist nodes to activated? """ from numpy import array, int16 graphnodes = self.graph.nodes(data=False) if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') if len(sellist) == 0: self.unselect_all() return from numpy import array, append tmparr = array([]) for node in sellist: # check if it is a valid graph node id if node in graphnodes: # get the node id as integer j = int(node.lstrip('n'))-1 # extend empty array with node id tmparr = append(tmparr, j) self.rendermanager._select_nodes(selection_node_array = array(tmparr, dtype = int16), activate = activate) def get_selectiongraph_list(self): """ Returns a list of the node ids that were selected in the rendered scene. """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') import numpy as np sel_list = [] if not self.active: return sel_list selnodesarray = self.datasourcemanager._srcobj.selected_nodes # array with indices where the nodes are selected (==1) idx = np.where(selnodesarray == 1)[0] for i in idx: sel_list.append('n' + str(i + 1)) return sel_list def set_weight_key(self, weight_key = None): """ Sets the weight key in the graph representation of the network. Parameters ---------- weight_key : Str Must be a possible existing edge key """ if not weight_key is None: for u,v,d in self.graph.edges(data=True): self.graph[u][v]['weight']=d[weight_key] return True else: return False def get_matrix(self, weight_key = None): """ Returns the connectivity matrix of the network with the nodes ordered according to their id in the GraphML file. Parameters ---------- weight_key : Str Possible key value of the edges Returns ------- matrix : `Numpy.array` instance The connectivity matrix """ nr_nodes = len(self.graph.nodes()) if not weight_key is None: #FIXME: sanity check if weight_key exists # thanks to Aric Hagberg for u,v,d in self.graph.edges(data=True): self.graph[u][v]['weight']=d[weight_key] nodes = [(lambda nmod:'n'+str(nmod))(node) for node in range(1,nr_nodes + 1)] from networkx import to_numpy_matrix return to_numpy_matrix(self.graph, nodelist = nodes) def toggle_surface(self): """ Toggle the surface for the selected network nodes """ if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') self.rendermanager._toggle_surface() def show_surface(self): """ Shows the surface for the selected network nodes """ if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') self.rendermanager._show_surface() def load_pickled_graphml(self, graph): """ Loads a pickled GraphML file Parameters ---------- graph : NetworkX Graph instance A graph instance """ # setting the graph self.graph = graph if self.graph.has_node('n0'): if self.graph.node['n0'].has_key('nodekeys'): # extracting the node keys from the first node self.nodekeys = self.graph.node['n0']['nodekeys'] # extracting the edge keys from the first edge (without explanation) if self.graph.node['n0'].has_key('edgekeys'): self.edgekeys = self.graph.node['n0']['edgekeys'] if self.graph.node['n0'].has_key('graphid'): self.networkid = self.graph.node['n0']['graphid'] # remove node self.graph.remove_node('n0') def _return_default_edgevalue(self, edgekeys, key): """ Looks up if there is a default value defined, otherwise return zero """ if edgekeys[key].has_key('default'): return float(edgekeys[key]['default']) else: return 0.0 def parse_network_graphml(self, path): """ Read network in GraphML format from a path. Parameters ---------- path : string path the the GraphML file Returns ------- graph : NetworkX `Graph` """ import networkx as nx from networkx.utils import _get_fh from lxml import etree # Return a file handle for given path. # Path can be a string or a file handle. # Attempt to uncompress/compress files ending in .gz and .bz2. fh=_get_fh(path,mode='r') tree = etree.parse(fh) # get the root node from parsed lxml root = tree.getroot() # Schema Validation # http://codespeak.net/lxml/validation.html#xmlschema # define the namespace prefixes nsprefix = "{%s}" % root.nsmap[None] nsxlink = "{%s}" % root.nsmap['xlink'] nodekeys = {} edgekeys = {} defaultDirected = [True] # Parse the KEYs for child in root.iterchildren(): if child.tag == (nsprefix+'key'): attribs = child.attrib ddkeys = {} for mchildren in child: if mchildren.tag == (nsprefix+'default'): ddkeys['default'] = mchildren.text elif mchildren.tag == (nsprefix+'desc'): ddkeys['desc'] = mchildren.text if child.attrib['for'] == 'node': # Parse all the node keys # Read in the description and the default (if existing) # dict of dicts for nodes: key1: the id; key2: rest: attr.name, attr.type, desc, default nodekeys[attribs['id']] = {'attr.name' : attribs['attr.name'], \ 'attr.type' : attribs['attr.type']} # add default/desc keys if existing nodekeys[attribs['id']] = ddkeys elif child.attrib['for'] == 'edge': # Parse all the edge keys # Read in the description and the default (if existing) # dict of dicts for edges: key1: the id; key2: rest: attr.name, attr.type, desc, default edgekeys[attribs['id']] = {'attr.name' : attribs['attr.name'], \ 'attr.type' : attribs['attr.type']} # add default/desc keys if existing edgekeys[attribs['id']] = ddkeys else: logger.error("The 'for' attribute of key-tag not known, must be either node or edge") elif child.tag == (nsprefix+'graph'): # start parsing the graph into networkx data structure # create graph depending on (either AttrGraph or AttrDiGraph) # directionality: undirected/directed # version of networkx: # contains self-loops # edges have dicts # data per graph/node/edge for attr, value in child.items(): if attr == 'edgedefault' and value == 'undirected': defaultDirected[0] = False elif attr == 'id': graphid = value if defaultDirected[0]: G = nx.DiGraph() else: G = nx.Graph() # add id, nodekeys and edkeys as traits self.networkid = graphid self.nodekeys = nodekeys self.edgekeys = edgekeys # iterate over all nodes and edges for children in child.iterchildren(): if children.tag == (nsprefix+'node'): # parse the node for attr, value in children.items(): if attr == 'id': # add the node with corresponding id G.add_node(value) # keep node id to store attributes nodeid = value elif attr == (nsxlink+'href'): # add xlink to node dictionary G.node[nodeid]['xlink'] = value else: # node attribute not known logger.warning('The following node attribute is not known and thus discarded:'+ attr + ':' + value) # parse node data, add to node dict for data in children.iterchildren(): # read the keylabel, i.e. the data attribute name keylabel = data.attrib['key'] # is the keylabel in the list of allowed keys if nodekeys.has_key(keylabel): if not data.text == '': # add data to the node's dict G.node[nodeid][keylabel] = data.text else: # no data available, check if default value exists if nodekeys[keylabel].has_key('default'): # add default data to the node's dict G.node[nodeid][keylabel] = nodekeys[keylabel]['default'] logger.debug('Added default value '+ keylabel + ':' + nodekeys[keylabel]['default']) else: logger.warning('Nor data nor default value defined for ' + keylabel) # TODO: Work with exceptions! else: logger.warning("Data entry with key " + keylabel + " not defined.") elif children.tag == (nsprefix+'edge'): # parse the edge # parse its attributes for attr, value in children.items(): if attr == 'id': # no usage of edge id # add the edge with corresponding id src = children.attrib['source'] tar = children.attrib['target'] G.add_edge(src, tar) # keep dest and tar id to store attributes srcid = src tarid = tar elif attr == (nsxlink+'href'): # add xlink to edge dictionary G.edge[srcid][tarid]['xlink'] = value # parse data, and add to the edge dict for data in children.iterchildren(): # read the keylabel, i.e. the data attribute name keylabel = data.attrib['key'] # is the keylabel in the list of allowed keys if self.edgekeys.has_key(keylabel): if not data.text == '': # add data to the edge's dict, assume float!! G.edge[srcid][tarid][keylabel] = float(data.text) else: # no data available, check if default value exists G.edge[srcid][tarid][keylabel] = self._return_default_edgevalue(self.edgekeys, keylabel) data_keys = G.edge[srcid][tarid].keys() # check if we missed some edge keys that are available in the header for k, v in self.edgekeys.items(): if not k in data_keys: G.edge[srcid][tarid][k] = self._return_default_edgevalue(self.edgekeys, k) # return the generated network graph return G
print('{0}/{1} nodes processed'.format(i, n)) print('Delete {0} orphaned nodes'.format(len(orphaned))) graph.remove_nodes_from(orphaned) print('Calculate offset') points = [node[1]['pos'] for node in graph.nodes(data=True)] min_x = min(points, key=lambda p: p[0])[0] min_y = min(points, key=lambda p: p[1])[1] for node in graph.nodes_iter(): pos = (graph.node[node]['pos'][0] - min_x, graph.node[node]['pos'][1] - min_y) graph.node[node]['pos'] = pos print('Translated data by ({0}, {1})'.format(-min_x, -min_y)) print('Calculate edge weights') n = graph.number_of_edges() i = 0 for edge in graph.edges(): lat1 = math.radians(graph.node[edge[0]]['lat']) lon1 = math.radians(graph.node[edge[0]]['lon']) lat2 = math.radians(graph.node[edge[1]]['lat']) lon2 = math.radians(graph.node[edge[1]]['lon']) graph[edge[0]][edge[1]]['weight'] = distance(lat1, lon1, lat2, lon2) i += 1 print('{0}/{1} edges processed'.format(i, n), end='\r') print('{0}/{1} edges processed'.format(i, n)) print('Write {0}'.format(output_file)) write_gpickle(graph, output_file) stop = timeit.default_timer() print('Program ran in {0} seconds'.format(stop - start))
class Topo(object): "Data center network representation for structured multi-trees." def __init__(self, hopts=None, sopts=None, lopts=None, ropts=None): """Topo object: hinfo: default host options sopts: default switch options lopts: default link options""" self.g = Graph() self.node_info = {} self.link_info = {} # (src, dst) tuples hash to EdgeInfo objects self.hopts = {} if hopts is None else hopts self.ropts = {} if ropts is None else ropts self.sopts = {} if sopts is None else sopts self.lopts = {} if lopts is None else lopts self.ports = {} # ports[src][dst] is port on src that connects to dst def addNode(self, name, **opts): """Add Node to graph. name: name opts: node options returns: node name""" self.g.add_node(name) self.node_info[name] = opts return name def addHost(self, name, **opts): """Convenience method: Add host to graph. name: host name opts: host options returns: host name""" if not opts: if self.hopts: opts = self.hopts elif self.ropts: opts = self.ropts return self.addNode(name, **opts) def addSwitch(self, name, **opts): """Convenience method: Add switch to graph. name: switch name opts: switch options returns: switch name""" if not opts and self.sopts: opts = self.sopts result = self.addNode(name, isSwitch=True, **opts) return result def addLink(self, node1, node2, port1=None, port2=None, **opts): """node1, node2: nodes to link together port1, port2: ports (optional) opts: link options (optional) returns: link info key""" if not opts and self.lopts: opts = self.lopts self.addPort(node1, node2, port1, port2) key = tuple(self.sorted([node1, node2])) self.link_info[key] = opts self.g.add_edge(*key) return key def addPort(self, src, dst, sport=None, dport=None): '''Generate port mapping for new edge. @param src source switch name @param dst destination switch name ''' self.ports.setdefault(src, {}) self.ports.setdefault(dst, {}) # New port: number of outlinks + base src_base = 1 if self.isSwitch(src) else 0 dst_base = 1 if self.isSwitch(dst) else 0 if sport is None: sport = len(self.ports[src]) + src_base if dport is None: dport = len(self.ports[dst]) + dst_base self.ports[src][dst] = sport self.ports[dst][src] = dport def nodes(self, sort=True): "Return nodes in graph" if sort: return self.sorted( self.g.nodes() ) else: return self.g.nodes() def isSwitch(self, n): '''Returns true if node is a switch.''' info = self.node_info[n] return info and info.get('isSwitch', False) def switches(self, sort=True): '''Return switches. sort: sort switches alphabetically @return dpids list of dpids ''' return [n for n in self.nodes(sort) if self.isSwitch(n)] def hosts(self, sort=True): '''Return hosts. sort: sort hosts alphabetically @return dpids list of dpids ''' return [n for n in self.nodes(sort) if not self.isSwitch(n)] def links(self, sort=True): '''Return links. sort: sort links alphabetically @return links list of name pairs ''' if not sort: return self.g.edges() else: links = [tuple(self.sorted(e)) for e in self.g.edges()] return sorted( links, key=naturalSeq ) def port(self, src, dst): '''Get port number. @param src source switch name @param dst destination switch name @return tuple (src_port, dst_port): src_port: port on source switch leading to the destination switch dst_port: port on destination switch leading to the source switch ''' if src in self.ports and dst in self.ports[src]: assert dst in self.ports and src in self.ports[dst] return (self.ports[src][dst], self.ports[dst][src]) def linkInfo( self, src, dst ): "Return link metadata" src, dst = self.sorted([src, dst]) return self.link_info[(src, dst)] def setlinkInfo( self, src, dst, info ): "Set link metadata" src, dst = self.sorted([src, dst]) self.link_info[(src, dst)] = info def nodeInfo( self, name ): "Return metadata (dict) for node" info = self.node_info[ name ] return info if info is not None else {} def setNodeInfo( self, name, info ): "Set metadata (dict) for node" self.node_info[ name ] = info @staticmethod def sorted( items ): "Items sorted in natural (i.e. alphabetical) order" return sorted(items, key=natural)
class LangGraph(object): """ A graph of all the relationships in a document and/or sentence """ def __init__(self, directed=False): """ Builds a graph out of the given document """ self.isDirected = directed #a graph that is meant to be full of class Instance if self.isDirected: self.graph = DiGraph() else: self.graph = Graph() self.start = None #an Instance #keep the graph also according to temporal, redundant probably needs #refactoring self.temporal = None self.temporalMap = None def setStart(self, start): """ Sets the starting instance, also builds the temporal ordering of the graph """ self.start = start self.temporal = self.narrativeOrder() self.temporalMap = self.narrativeMapping() def indexToInst(self, index): """ Returns the instance corresponding to the given index """ result = index #if the index is an int, lookup the instance associated with it if type(index) == int: result = self.temporal[index] return result def instToIndex(self, instance): """ Return the index associated with the instance """ return self.temporalMap[instance] def narrativeOrder(self): """ Returns the instances in narrative order """ results = [] node = self.start prev = None #while there are more nodes, keep adding them while node is not None: #record the current node results.append(node) #get the connected nodes fringe = [n for n in self.adj(node, WORD_EDGE) if n != prev] nextNode = fringe[0] if fringe else None #advance to the next node prev = node node = nextNode return results def narrativeMapping(self): """ Makes the mapping from instances to their narrative index """ return {inst:i for i,inst in enumerate(self.temporal)} def addNode(self, node): """ Adds a node to the graph """ self.graph.add_node(node) def addEdge(self, start, end, type): """ Adds an edge between the two instances """ #if the edge exists, just add the type if self.graph.has_edge(start, end): self.addType(start, end, type) else: self.graph.add_edge(start, end, TYPES=set([type])) def removeEdge(self, start, end, edgeType): """ Removes an edge with a given type from the edge type """ #remove the type self.removeType(start, end, edgeType) #if there are no types, remove the edge itself types = self.edgeTypes(start, end) #remove the edge if not len(types) and self.graph.has_edge(start, end): self.graph.remove_edge(start, end) def addType(self, start, end, type): """ Adds a type between the edges """ #look for existing types types = self.graph[start][end].get(TYPES, set()) #add the new type types.add(type) self.graph[start][end][TYPES] = types def removeType(self, start, end, edgeType): """ Removes the type on the edge """ for prefix in [PARENT, CHILD]: edgeType = removePrefix(prefix, edgeType) types = self.graph[start][end][TYPES] #if the types contains the edge, remove if edgeType in types: types.remove(edgeType) def hasType(self, start, end, type): """ Returns true if the edge between the two nodes has the given type """ return type in self.edgeTypes(start, end) def singleEdgeTypes(self, start, end): """ Returns the types on the edge if any, or an empty set is returned """ #make sure we are using instances rather than indexes start = self.indexToInst(start) end = self.indexToInst(end) data = self.graph.get_edge_data(start,end) result = set() #if there is data, get the types if data is not None: result = data.get(TYPES, set()) return result def edgeTypes(self, start, end): """ Returns the types on the edge if any, or an empty set is returned """ if self.isDirected: parent = addPrefixes(PARENT, self.singleEdgeTypes(end, start)) child = addPrefixes(CHILD, self.singleEdgeTypes(start, end)) types = parent.union(child) else: types = self.singleEdgeTypes(start, end) return types def allEdgeTypes(self): """ Returns all the edge types """ results = set() #collect all the edges with all the types for s,e,types in self.allEdges(): #look up the edge types to make sure everything is covered for edgeType in types: results.add(edgeType) #add in the reverse types for edgeType in self.edgeTypes(e,s): results.add(edgeType) return results def allEdges(self): """ Yield all the edges in the graph """ for start, end in self.graph.edges(): yield start, end, self.edgeTypes(start, end) def contains(self, instance): """ Returns true if the graph contains the instance """ return self.graph.has_node(instance) def instances(self): """ Return all the instances in the graph """ return self.graph.nodes() def edges(self, instance): """ Returns all the edges connected to this instance """ inst = self.indexToInst(instance) #make get the directed edges if self.isDirected: results = [t for _, t in self.graph.out_edges(inst)] + [t for t, _ in self.graph.in_edges(inst)] else: results = self.graph.adj[inst] return results def docType(self): """ Returns the document type (String) """ return self.temporal[0].event.docType def adj(self, instance, type=None): """ Returns the adjancent node with a given type """ return [other for other in self.edges(instance) if self.hasType(instance, other, type) or type is None] def nonNarrativeAdj(self, instance, returnIndex=False): """ Returns the nodes that are not adjancent to the given instance """ results = [] #add each node if it has a non-narrative (temporal) connection for node in self.edges(instance): #get the non narrative types edgeTypes = nonNarrativeTypes(self.edgeTypes(instance, node)) #if there is a non-narrative edge, add it if edgeTypes: #lookup the index of the node nodeMarker = self.instToIndex(node) if returnIndex else node results.append((nodeMarker, edgeTypes)) return results def words(self): """ Returns the words in narrative order """ return [t.word for t in self.tokens()] def tokens(self): """ Returns the tokens in narrative order """ return [i.token for i in self.temporal] def labels(self): """ Returns the sequence of labels for the instances """ return [i.event.type for i in self.temporal] def removeAny(self, blackList): """ Removes any nodes/tokens/instances that match the words in the blacklist """ #if a token or its lemma match any of the words in the blacklist #mark it for removal toRemove = {inst.token for inst in self.temporal if inst.token.word.lower() in blackList or inst.token.lemma.lower() in blackList} self.removeNodes(toRemove) def removeNodes(self, tokens): """ Removes the token from the graph """ startLen = len(self) #mark all the instances/indexes to remove instances = {inst:i for inst,i in self.temporalMap.items() if inst.token in tokens} #determine the remaining nodes remaining = sorted(list(set(range(startLen)) - {i for i in instances.values()})) #add in all the bypasses for startIndex, endIndex in iterPairs(remaining): start = self.temporal[startIndex] end = self.temporal[endIndex] self.addEdge(start, end, WORD_EDGE) #remove the edges for inst in instances: self.graph.remove_node(inst) #if there are remaining nodes then reset the temporal mapping if remaining: startIndex = min(remaining) self.start = self.temporal[startIndex] #redo narrative order self.temporal = self.narrativeOrder() self.temporalMap = self.narrativeMapping() else: self.start = None self.temporal = [] self.temporalMap = {} def copy(self): """ Performs a shallow copy of the graph """ newGraph = LangGraph(self.isDirected, self.entEdges) #create new instances newInst = {i:me.Instance(copy(i.token), i.event) for i in self.temporal} #add in all the edges for start, end in self.graph.edges(): for eType in self.edgeTypes(start, end): newGraph.addEdge(newInst[start], newInst[end], eType) newGraph.setStart(newInst[self.start]) return newGraph def graphString(self): """ Returns the graph as a string """ return " ".join([t.word for t in self.tokens()]) def __len__(self): """ Returns the number of nodes (tokens) in the graph """ return len(self.graph) def __repr__(self): """ Returns a summary string of the graph """ return "LangGraph {} nodes, {} edges".format(len(self.graph.nodes()), len(self.graph.edges()))