def find_random_tree(G, B, B_min, iterations): bridge_data = [] for u, v in nx.bridges(G): bridge_data.append((u, v, G[u][v])) non_bridges = [e for e in G.edges.data() if e not in bridge_data] mirror_friendly_spanning_tree = None for _ in range(iterations): guess = random.sample(non_bridges, k=len(G.nodes) - 1 - len(bridge_data)) temp_G = nx.Graph() temp_G.add_edges_from(guess) temp_G.add_edges_from(bridge_data) if nx.is_tree(temp_G): w_, mw_ = 0, 0 for u, v in temp_G.edges: w_ += temp_G[u][v]["weight"] mw_ += temp_G[u][v]["m_weight"] if max(w_, mw_) < B: print("The value of B is " + str(B)) # TODO: Remove B = max(w_, mw_) mirror_friendly_spanning_tree = temp_G if B == B_min: break print("The value of B is " + str(B)) # TODO: Remove return mirror_friendly_spanning_tree, B
def get_N_minus_1_branches(graph, branches, mapping_bus_to_idx): """ Gets a list of branches which can be monitored using N-1 tools Returns ------- List of branches for which removing one does not disconnect the network """ potential_bridges = set(nx.bridges(nx.Graph(graph))) ## networkx.bridges does not handle multi-edges cleanly, ## so we need to remove some it found if a redundant ## branch connects two nodes bridges_to_remove = set() for bridge in potential_bridges: swap = (bridge[1], bridge[0]) if graph[bridge] + graph[swap] > 1: bridges_to_remove.add(bridge) bridges = potential_bridges - bridges_to_remove branches_not_disconnecting = [] for bn, branch in branches.items(): idx_from, idx_to = mapping_bus_to_idx[branch['from_bus']], \ mapping_bus_to_idx[branch['to_bus']] if (idx_from, idx_to) in bridges: continue elif (idx_to, idx_from) in bridges: continue else: branches_not_disconnecting.append(bn) return branches_not_disconnecting
def EDGE_SP_bruteforce(G, edgeLimit, target): if edgeLimit == 0: return [] # 1. Calculate edges on SP that do not disconnect current graph. sp = shortestPath(G, target) sp_edges = [(sp[i], sp[i + 1]) for i in range(len(sp) - 1)] bridgeList = list(nx.bridges(G)) sp_edges = [edge for edge in sp_edges if ((edge not in bridgeList) and (edge[::-1] not in bridgeList))] # 2. If no edges can be removed along SP without disconnecting graph, break loop. Can no longer improve. if not sp_edges: return [] # 3. edgeDict = {} for edge in sp_edges: H = G.copy() H.remove_edge(edge[0], edge[1]) optimal_removed = EDGE_SP_bruteforce(H, edgeLimit - 1, target) H.remove_edges_from(optimal_removed) all_removed = [edge] + list(optimal_removed) edgeDict[tuple(all_removed)] = shortestPath(H, target) print(max(edgeDict, key=lambda x: edgeDict[x])) return list(max(edgeDict, key=lambda x: edgeDict[x]))
def find_musthave_edges(G): """ must_have_edges,all_edges = find_musthave_edges(G) both lists in form: [(u,v,'weight')...] """ edges = list(G.edges.data()) must_have_list = list( nx.bridges(G)) # bridges returns only the nodes (u,v) must_have_edges = [] for (u, v) in must_have_list: if u < v: edge = (u, v, (G[u][v])) else: edge = (v, u, (G[u][v])) must_have_edges.append(edge) all_edges = [] for (u, v, w) in edges: # each edge is (u,v,w['weight']) if u < v: edge = (u, v, w) else: edge = (v, u, w) all_edges.append(edge) return must_have_edges, all_edges
def naive_edge_solution(G, B, B_min): # First we find the bridges in the graph, then the non-bridge edges and finally # we make a generator that makes all combinations of edges from the non-bridge set # that are of length n - 1 - number of bridges. bridge_data = [] for u, v in nx.bridges(G): bridge_data.append((u, v, G[u][v])) non_bridges = [e for e in G.edges.data() if e not in bridge_data] combinations = itertools.combinations(non_bridges, len(G.nodes) - 1 - len(bridge_data)) # We iterate over all combinations, where we create the graph from the edges, # and check whether the graph is a tree (including connectivity). If it is # we calculate the weight and mirror weights and compare them to B. mirror_friendly_spanning_tree = None for comb in combinations: temp_G = nx.Graph() temp_G.add_edges_from(comb) temp_G.add_edges_from(bridge_data) if nx.is_tree(temp_G): w_, mw_ = 0, 0 for u, v in temp_G.edges: w_ += temp_G[u][v]["weight"] mw_ += temp_G[u][v]["m_weight"] if max(w_, mw_) < B: print("The value of B is now " + str(B)) B = max(w_, mw_) mirror_friendly_spanning_tree = temp_G if B == B_min: break # We stop if we hit the minimum value print("The value of B is now " + str(B)) return mirror_friendly_spanning_tree, B
def test_bridges(self): for _ in range(1000): while True: nxg = nx.fast_gnp_random_graph(randint(1, 10), randint(1, 9) / 10, directed=False) if nx.is_connected(nxg): break # for u, v in nxg.edges: # nxg[u][v]['weight'] = randint(1, 12) # print(sorted(nxg.nodes)) # print(sorted(nxg.edges)) g = gx.Graph() g.add_vertices_from(nxg.nodes) # for u, v in nxg.edges: # g.add_edge(u, v, nxg[u][v]['weight']) for u, v in nxg.edges: g.add_edge(u, v) # print(sorted(g.vertices)) # print(sorted(g.edges)) x = [(u, v) if u < v else (v, u) for u, v in list(nx.bridges(nxg))] y = [(u, v) if u < v else (v, u) for u, v in bridges(g)] if x and y: print(sorted(x)) print(sorted(y)) self.assertEqual(sorted(x), sorted(y))
def generate_random_graph(): """ generates random graphs: external loop - number of repeated generations; inner loop-number of different probabilities :return: saves generated graphs to json and as networkx adjlist """ for i in range(1, 100): for prob in range(1, 10): prob = float(prob / float(nodes * 10)) # den=nodes*10 G = nx.fast_gnp_random_graph(nodes, prob).to_undirected() res = {} try: res = nx.to_dict_of_lists(G) except TypeError: # Python 3.x sys.stdout("Error") size = len(list(nx.bridges(G))) # number of bridges file_name_adj = "random_{}_{}_{}.adj_list".format( nodes, prob, size) file_name_json = "random_{}_{}_{}.json".format(nodes, prob, size) file_path_adj = os.path.join(os.getcwd(), '..', 'res', file_name_adj) file_path_json = os.path.join(os.getcwd(), '..', 'res', file_name_json) # writing to .json with open(file_path_json, "w") as f: json.dump(res, f, indent=4) # writing to .adjlist fh = open(file_path_adj, 'wb+') nx.write_adjlist(G, fh)
def simple_cycle(unicycle): #returns the simple cycle of a unicycle #cycles= nx.simple_cycles(unicycle) bridges = list(nx.bridges(unicycle)) edge_list = list(unicycle.edges()) cycle_edges = [e for e in edge_list if e not in bridges] return cycle_edges
def fill_features(self): isolates = nx.isolates(self.graph) for node in isolates: self.graph.node[node]["isolate"] = True bridges = nx.bridges(self.graph) for node in isolates: self.graph.node[node]["isolate"] = True
def prepare(G, ratio): num_hidden = int(len(G.edges()) * ratio) posi, nega = [], [] all_edges, bridges = list(G.edges()), list(nx.bridges(G)) flag = 1 while flag: sampled_edges = np.random.choice(len(all_edges), size=num_hidden, replace=False) for edge in sampled_edges: edge = all_edges[edge] if edge in bridges or edge in posi: continue posi.append(edge) G.remove_edge(*edge) bridges = list(nx.bridges(G)) if len(posi) == num_hidden: flag = 0 break all_edges, all_nodes = list(G.edges()), list(G.nodes()) while len(nega) < num_hidden: n1, n2 = random.choice(all_edges) n3, n4 = random.choice(all_nodes), random.choice(all_nodes) pair1, pair2 = tuple(np.sort([n1, n3])), tuple(np.sort([n2, n4])) if not (n1 == n3 or pair1 in all_edges or pair1 in nega): nega.append(pair1) if not (n2 == n4 or pair2 in all_edges or pair2 in nega): nega.append(pair2) posi = np.concatenate( [np.array(posi), np.ones(len(posi), dtype=int).reshape(-1, 1)], axis=1) nega = np.concatenate( [np.array(nega), np.zeros(len(nega), dtype=int).reshape(-1, 1)], axis=1) prediction_links = np.concatenate([posi, nega], axis=0) return G, prediction_links
def set_bridges(G): if not any("Bridge" in G.edges[edge] for edge in G.edges): nx.set_edge_attributes(G, False, "Bridge") # Calculate bridges bridges = list(nx.bridges(G)) for edge in bridges: nx.set_edge_attributes(G, {edge: {"Bridge": True}}) G.graph["Bridges"] = len(bridges)
def get_bridges(self): res = [] if self.G.is_multigraph(): raise NotImplementedError("Multi Graph not supported.") else: for b in nx.bridges(self.G): if self.G.edges[b].get('amount', 0) == 1: res.append(b) return res
def test_singeEdge(self): ''' Just a single edge in the graph, so this must be the edge. ~~~ a-b ~~~ ''' G = nx.Graph() G.add_edge('a', 'b') assert_equal(list(bridges(G)), [('a', 'b')])
def get_graph_bridges(G): bridges = list(nx.bridges(G)) non_bridges = [edge for edge in G.edges if edge not in bridges] G2 = G.copy() G2.remove_edges_from(non_bridges) G2.remove_nodes_from(list(nx.isolates(G2))) return bridges, G2
def test_parallelEdge(self): ''' a----b \__/ ''' G = nx.MultiGraph() G.add_edge(1, 2) G.add_edge(1, 2) print G.edges(), G[1][2] assert_equal(list(bridges(G)), [])
def remove_bridges(GG, min_counts_strict): selected_edges = [(u,v) for u,v,e in GG.edges(data=True) if e['conf'] == True] gg_conf=GG.edge_subgraph(selected_edges) brlist=list(nx.bridges(gg_conf)) for edge in brlist: curedge=GG.edges[edge] if sum(curedge['cts'])<min_counts_strict: if abs(curedge['mns'][0]-curedge['mns'][3])>350 or abs(curedge['mns'][1]-curedge['mns'][2])>350: GG.edges[edge].update({'conf': False})
def print_statistics(self): message("-------------------------------------------") message("-- Graph Statistics -----------------------") message() message(" isolates:", nx.number_of_isolates(self.graph)) message(" density:", nx.density(self.graph)) message(" bridges:", len(list(nx.bridges(self.graph)))) message(" cliques:", nx.graph_clique_number(self.graph)) message(" conn-comps:", nx.number_connected_components(self.graph)) message() message("-------------------------------------------")
def eval_edges(edges, mentions, model, doc_dict): print(len(mentions)) global best_score, patience dot = Graph(comment='Cross Doc Co-ref') G = nx.Graph() edges = sorted(edges, key=lambda x: -1 * x[3]) for mention in mentions: G.add_node(mention.mention_id) dot.node(mention.mention_id, label=str((str(mention), doc_dict[mention.doc_id].sentences[ mention.sent_id].get_raw_sentence()))) bridges = list(nx.bridges(G)) articulation_points = list(nx.articulation_points(G)) #edges = [edge for edge in edges if edge not in bridges] clusters, inv_clusters = transitive_closure_merge(edges, mentions, model, doc_dict, G, dot) # Find Transitive Closure Clusters gold_sets = [] model_sets = [] ids = [] model_map = {} gold_map = {} for mention in mentions: ids.append(mention.mention_id) gold_sets.append(mention.gold_tag) gold_map[mention.mention_id] = mention.gold_tag if mention.mention_id in inv_clusters: model_map[mention.mention_id] = inv_clusters[mention.mention_id] model_sets.append(inv_clusters[mention.mention_id]) else: model_map[mention.mention_d] = mention.mention_id model_sets.append(mention.mention_id) model_clusters = [[thing[0] for thing in group[1]] for group in itertools.groupby(sorted(zip(ids, model_sets), key=lambda x: x[1]), lambda x: x[1])] gold_clusters = [[thing[0] for thing in group[1]] for group in itertools.groupby(sorted(zip(ids, gold_sets), key=lambda x: x[1]), lambda x: x[1])] pn, pd = b_cubed(model_clusters, gold_map) rn, rd = b_cubed(gold_clusters, model_map) tqdm.write("Alternate = Recall: {:.6f} Precision: {:.6f}".format(pn/pd, rn/rd)) p, r, f1 = bcubed(gold_sets, model_sets) tqdm.write("Recall: {:.6f} Precision: {:.6f} F1: {:.6f}".format(p, r, f1)) if best_score == None or f1 > best_score: tqdm.write("F1 Improved Saving Model") best_score = f1 patience = 0 if not args.evaluate_dev: torch.save(model.state_dict(), os.path.join(args.out_dir, 'best_model')) else: dot.render('/home/ubuntu/clustering') else: patience += 1 if patience > config_dict["early_stop_patience"]: print("Early Stopping") sys.exit()
def reduction_rule_3(graph, oct_set): """ Remove bridges. """ # print("Entered RR3") changed = False bridges = list(nx.bridges(graph)) if len(bridges) > 0: changed = True # Update the graph's preprocessing statistics graph.graph['edges_removed'] += len(bridges) # Execute the removal graph.remove_edges_from(bridges) # Sanity check: Shouldn't have any bridges! assert (len(list(nx.bridges(graph))) == 0) # print("Exited RR3") return changed, graph, oct_set
def remove_bridges(GG, min_counts_strict): bridges = [] brlist = list(nx.bridges(GG)) for edge in brlist: curedge = GG.edges[edge] if sum(curedge['cts']) < min_counts_strict: if abs(curedge['mns'][0] - curedge['mns'][3]) > 350 or abs(curedge['mns'][1] - curedge['mns'][2]) > 350: bridges.append(curedge) GG.remove_edge(edge[0], edge[1]) return bridges
def __call__(self, action, env, has_error, is_done, is_illegal, is_ambiguous): if has_error or is_illegal or is_ambiguous: return self.reward_min n_bus = 2 # Get info from env obs = env.current_obs n_sub = obs.n_sub n_line = obs.n_line topo = obs.topo_vect or_topo = obs.line_or_pos_topo_vect ex_topo = obs.line_ex_pos_topo_vect or_sub = obs.line_or_to_subid ex_sub = obs.line_ex_to_subid # Create a graph of vertices # Use one vertex per substation per bus G = nx.Graph() # Set lines edges for current bus for line_idx in range(n_line): # Skip if line is disconnected if obs.line_status[line_idx] is False: continue # Get substation index for current line lor_sub = or_sub[line_idx] lex_sub = ex_sub[line_idx] # Get the buses for current line lor_bus = topo[or_topo[line_idx]] lex_bus = topo[ex_topo[line_idx]] if lor_bus <= 0 or lex_bus <= 0: continue # Compute edge vertices indices for current graph left_v = lor_sub + (lor_bus - 1) * n_sub right_v = lex_sub + (lex_bus - 1) * n_sub # Register edge in graph G.add_edge(left_v, right_v) # Find the bridges n_bridges = dt_float(len(list(nx.bridges(G)))) # Clip to min penalty n_bridges = max(n_bridges, self.min_pen_lte) # Clip to max penalty n_bridges = min(n_bridges, self.max_pen_gte) r = np.interp(n_bridges, [self.min_pen_lte, self.max_pen_gte], [self.reward_max, self.reward_min]) return dt_float(r)
def test_single_bridge(self): edges = [ # DFS tree edges. (1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (6, 7), (7, 8), (5, 9), (9, 10), # Nontree edges. (1, 3), (1, 4), (2, 5), (5, 10), (6, 8) ] G = nx.Graph(edges) source = 1 bridges = list(nx.bridges(G, source)) self.assertEqual(bridges, [(5, 6)])
def getBridges(G): bridges = {} for brg in nx.bridges(G.to_undirected()): if (brg[1], brg[0]) in G.edges: bridges[(brg[1], brg[0])] = G.get_edge_data(brg[1], brg[0], 'weight')['weight'] else: bridges[brg] = G.get_edge_data(brg[0], brg[1], 'weight')['weight'] sorted_brgs = sorted(bridges.items(), key=operator.itemgetter(1), reverse=True) return sorted_brgs
def test_twoDisconnectedComponents(self): ''' ~~~ a-b-c e-f-g ~~~ ''' G=nx.Graph() G.add_edge(1, 2) G.add_edge(3, 4) # Both edges are bridges. assert_equal(list(bridges(G)), [(1, 2), (3, 4)])
def test_triangle(self): ''' ~~~ a---b \ / c ~~~ ''' G = nx.Graph() G.add_edge(1, 2) G.add_edge(2, 3) G.add_edge(3, 1) # Graph forms a triangle so no edge is a bridge. assert_equal(list(bridges(G)), [])
def pick_action(g, rand): """Randomly picks a valid action (add / remove link).""" actions = [] # We can remove any edge as long as the removal doesn't cause a partition. actions.extend(("del", u, v) for u, v in set(g.edges) - set(nx.bridges(g))) # We can add any router-to-router edge that doesn't exist yet. # Hosts are ignored since we can't connect a host to multiple routers. actions.extend( ("add", u, v) for u, v in nx.non_edges(g) if (not isinstance(g.nodes[u]["entity"], api.HostEntity) and not isinstance(g.nodes[v]["entity"], api.HostEntity))) actions.sort(key=lambda a: (a[0], g.nodes[a[1]]["entity"].name, g.nodes[a[ 2]]["entity"].name)) return rand.choice(actions)
def generate_graph(grid_decomposition, gridpoints, grid_min, grid_shape, gridspace=1.0, min_degree=3, radius=2, score=500): """ Generate a graph from cavity points. It connects nodes if they are within gridspace distance. It removes self loops and bridges. ################# ADDED TRIMMING OF CAVITY POINTS ################################# Uses trim_cavity_bylocalweight which is in cavity_characterization.gridpoint_properties.py Originally this function was supposed to trim cavities later """ # Find cavity points indices and extract their coordinates cavity_point = np.where(grid_decomposition > 1)[0] cav_coor = gridpoints[cavity_point] trimmed_cavs = trim_cavity_bylocalweight(cav_coor, grid_min, grid_shape, grid_decomposition, radius, score) setcav = SetOfPoints(trimmed_cavs) diag = gridspace + 0.1 # +0.1 because floating point #*np.sqrt(3) was for the diagonal connections # but it ended up overspanning if len(trimmed_cavs) == 0: return None, None dist_mat = setcav.print_indices_within(trimmed_cavs, diag, turnon=False) list_edges = dist_mat[["i", "j"]] G = nx.Graph() # Initialize graph G.add_edges_from(list_edges) # Remove self edges G.remove_edges_from(nx.selfloop_edges(G)) # Remove nodes with few connections remove = [ node for node, degree in dict(G.degree()).items() if degree < min_degree ] G.remove_nodes_from(remove) # List and remove bridges. There should probably not be any? bridges = list(nx.bridges(G)) G.remove_edges_from(bridges) return G, trimmed_cavs
def get_randomness(G, p): G.remove_nodes_from(list(nx.isolates(G))) spread = [] spread_paths = [] for j in range(1, len(list(G))): spread.append(G) spread_paths.append(nx.average_shortest_path_length(G)) if random.randint(0, 100) < p * 100: edges = list(set(G.edges) - set(nx.bridges(G))) if edges: u, v = random.choice(edges) G.remove_edge(u, v) w = random.choice( list(set(G) - set(x for _, x in set(G.edges(u))))) G.add_edge(u, w) return spread, spread_paths
def EDGE_avoidMakingBridges(G, sp_edges): num_bridges_after_removing_each_edge = {} for edge in sp_edges: H = G.copy() H.remove_edge(edge[0], edge[1]) bridgeList = list(nx.bridges(H)) num_bridges_after_removing_each_edge[edge] = len(bridgeList) #sp_edges.sort(key=lambda edge: random.expovariate(0.5*num_bridges_after_removing_each_edge[edge]), reverse=True) sp_edges.sort(key=lambda edge: num_bridges_after_removing_each_edge[edge], reverse=True) if len(sp_edges) > 1: spice = sp_edges[1:] random.shuffle(spice) test = random.uniform(0, 1) if test > 0.85: sp_edges[0] = spice[0]
def __find_bridges_overlap(self): if nx.is_directed(self.__g): raise TypeError("Not implemented for directed graphs") self.__bridges = list(nx.bridges(self.__g)) for edge in self.__g.edges: n1, n2 = edge[0], edge[1] comm_neighbors = len(list(nx.common_neighbors(self.__g, n1, n2))) if comm_neighbors == 0: self.__local_bridges.append(edge) neighbor_n1 = set(self.__g.neighbors(n1)) neighbor_n2 = set(self.__g.neighbors(n2)) total_neighbors = len(neighbor_n1 | neighbor_n2) self.__neigh_overlap["{}-{}".format( n1, n2)] = comm_neighbors / total_neighbors
def EDGE_SPrandom(G, edgeLimit, target, heuristic): ##### #cumulative = 0 ##### to_remove = [] for i in range(edgeLimit): # 1. Calculate edges on SP that do not disconnect current graph. sp = shortestPath(G, target) sp_edges = [(sp[i], sp[i + 1]) for i in range(len(sp) - 1)] bridgeList = list(nx.bridges(G)) sp_edges = [edge for edge in sp_edges if (edge not in bridgeList) and (edge[::-1] not in bridgeList)] #### # print("Don't remove: " + str(bridgeList)) # print("Considered for removal: " + str(sp_edges)) # print("Iteration: " + str(i)) #### # 2. If no edges can be removed along SP without disconnecting graph, break loop. Can no longer improve. if not sp_edges: break ######## # test = sp_edges.copy() # test.sort(key=lambda edge: G[edge[0]][edge[1]]['weight']) ######## # 3. Sort edges by heuristic. Remove first one. heuristic(G, sp_edges) ############ # if sp_edges[0] == test[0]: # cumulative += 1 # print("Average accuracy: " + str(cumulative / (i + 1))) ################ first_edge = sp_edges[0] G.remove_edge(first_edge[0], first_edge[1]) to_remove.append(first_edge) return to_remove
def detectParameterizableCores(graph): """ Detect parametrizable dihedral angle cores (central atom pairs) The cores are detected by looking for bridges (bonds which divide the molecule into two parts) in a molecular graph. Terminal cores are skipped. """ methyl = _getMethylGraph() all_core_sides = [] for core in list(nx.bridges(graph)): # Get side graphs of the core graph.remove_edge(*core) sideGraphs = list(connected_component_subgraphs(graph)) graph.add_edge(*core) # Skip terminal bridges, which cannot form dihedral angles if len(sideGraphs[0]) == 1 or len(sideGraphs[1]) == 1: continue # Swap the side graphs to match the order of the core sideGraphs = sideGraphs[::-1] if core[0] in sideGraphs[ 1] else sideGraphs assert core[0] in sideGraphs[0] and core[1] in sideGraphs[1] # Skip if a side graph is a methyl group if _checkIsomorphism(sideGraphs[0], methyl) or _checkIsomorphism( sideGraphs[1], methyl): continue # Skip if core contains C with sp hybridization if graph.nodes[core[0]]['element'] == 'C' and graph.degree( core[0]) == 2: continue if graph.nodes[core[1]]['element'] == 'C' and graph.degree( core[1]) == 2: continue all_core_sides.append((core, sideGraphs)) return all_core_sides
def buildNet(): form = UserNetwork() user = None numUsers = None net = None nodes = None edges = None data = None bridges = None central = None if form.validate_on_submit(): user = form.user.data numUsers = form.numUsers.data net = buildNetwork(user, numUsers) bb = nx.current_flow_betweenness_centrality(net, weight="weight") central = sorted(bb.items(), key=lambda kv: kv[1], reverse=True)[0:5] nx.set_node_attributes(net, bb, "betweenness") degree = nx.degree_centrality(net) nx.set_node_attributes(net, degree, "degree") data = nx.node_link_data(net) bridges = list(nx.bridges(net)) timeStamp = time.strftime("%Y%m%d-%H%M%S") with open( os.path.join(os.getcwd(), f"app\\static\\data\\data_file_{timeStamp}.json"), "w") as write_file: json.dump(data, write_file) data = f"/static/data/data_file_{timeStamp}.json" #, fp=(os.path.join(os.getcwd(), "\\app\\static\\data\\net.json"))) #formattedNodes = "nodes: [\n" #for node in net.nodes(): # fN = '{\n data: { id: %s }\n},\n' %node # formattedNodes += fN return render_template("networks.html", form=form, user=user, numUsers=numUsers, net=net, nodes=nodes, edges=edges, data=data, bridges=bridges, central=central)
def find_non_cyclic_edges(self, subgraph): """ Generates a set of edges of the subgraph that are not in a cycle (called "bridges" in networkX terminology). Parameters --------- subgraph : NetworkX subgraph obj the subgraph to check for not cycle nodes Returns ------- missingEdgesSet : set of graph edges the set of edges that are not in a cycle """ missingEdgesSet = set(nx.bridges(subgraph)) return missingEdgesSet
def test_twoCycles(self): ''' a---b \ / c | d / \ e---f ''' G=nx.Graph() G.add_edge('a', 'b') G.add_edge('b', 'c') G.add_edge('c', 'a') G.add_edge('c', 'd') G.add_edge('d', 'e') G.add_edge('e', 'f') G.add_edge('f', 'd') assert_equal(list(bridges(G)), [('c', 'd')])
def detectParameterizableCores(graph): """ Detect parametrizable dihedral angle cores (central atom pairs) The cores are detected by looking for bridges (bonds which divide the molecule into two parts) in a molecular graph. Terminal cores are skipped. """ methyl = _getMethylGraph() all_core_sides = [] for core in list(nx.bridges(graph)): # Get side graphs of the core graph.remove_edge(*core) sideGraphs = list(connected_component_subgraphs(graph)) graph.add_edge(*core) # Skip terminal bridges, which cannot form dihedral angles if len(sideGraphs[0]) == 1 or len(sideGraphs[1]) == 1: continue # Swap the side graphs to match the order of the core sideGraphs = sideGraphs[::-1] if core[0] in sideGraphs[1] else sideGraphs assert core[0] in sideGraphs[0] and core[1] in sideGraphs[1] # Skip if a side graph is a methyl group if _checkIsomorphism(sideGraphs[0], methyl) or _checkIsomorphism(sideGraphs[1], methyl): continue # Skip if core contains C with sp hybridization if graph.nodes[core[0]]['element'] == 'C' and graph.degree(core[0]) == 2: continue if graph.nodes[core[1]]['element'] == 'C' and graph.degree(core[1]) == 2: continue all_core_sides.append((core, sideGraphs)) return all_core_sides
def weakly_biconnected_component_subdigraphs(G): """ >>> G = nx.DiGraph() >>> G.add_edge('a', 'c') >>> G.add_edge('b', 'c') >>> G.add_edge('c', 'd') >>> G.add_edge('c', 'e') >>> G.add_edge('x', 'y') >>> G.add_node('z') >>> for n in G.nodes_iter(): ... G.node[n]['attr'] = n >>> for e in G.edges_iter(): ... G[e[0]][e[1]]['attr'] = '->'.join([str(i) for i in e]) >>> for g in weakly_biconnected_component_subdigraphs(G): ... print '------------------' ... print g.nodes(data=True) ... print g.edges(data=True) ------------------ [('a', {'attr': 'a'}), ('c', {'attr': 'c'}), ('b', {'attr': 'b'})] [('a', 'c', {'attr': 'a->c'}), ('b', 'c', {'attr': 'b->c'})] ------------------ [('c', {'attr': 'c'}), ('e', {'attr': 'e'}), ('d', {'attr': 'd'})] [('c', 'e', {'attr': 'c->e'}), ('c', 'd', {'attr': 'c->d'})] ------------------ [('y', {'attr': 'y'}), ('x', {'attr': 'x'})] [('x', 'y', {'attr': 'x->y'})] ------------------ [('z', {'attr': 'z'})] [] """ if not G.is_directed(): raise nx.NetworkXError('Input graph must be a digraph') if not all(isinstance(n, basestring) for n in G): raise nx.NetworkXError('Node names must all be strings.') split_G=nx.DiGraph(G) nx.algorithms.split_pass_through_node_digraph(split_G) #print '==================' #print split_G.nodes() #print split_G.edges() for e in nx.bridges(nx.Graph(split_G)): m0 = re.match('^(.*):(o|i)$', e[0]) m1 = re.match('^(.*):(o|i)$', e[1]) if m0 is not None and m1 is not None: if m0.group(1) == m1.group(1) and m0.group(2) != m1.group(2): split_G.remove_edge(':'.join((m0.group(1), 'i')), ':'.join((m0.group(1), 'o'))) for wcc in nx.weakly_connected_component_subgraphs(split_G): def extract_original_node(n): m = re.match('^(.*):(o|i)$', n) if m is not None: return m.group(1) else: return n subgraph_nodes = set([extract_original_node(n) for n in wcc]) yield G.subgraph(subgraph_nodes)
def test_barbell_graph(self): # The (3, 0) barbell graph has two triangles joined by a single edge. G = nx.barbell_graph(3, 0) source = 0 bridges = list(nx.bridges(G, source)) self.assertEqual(bridges, [(2, 3)])
def mask_test_edges_directed(adj, test_frac=.1, val_frac=.05, prevent_disconnect=True, verbose=False, false_edge_sampling='iterative'): if verbose == True: print 'preprocessing...' # Remove diagonal elements adj = adj - sp.dia_matrix((adj.diagonal()[np.newaxis, :], [0]), shape=adj.shape) adj.eliminate_zeros() # Check that diag is zero: assert np.diag(adj.todense()).sum() == 0 # Convert to networkx graph to calc num. weakly connected components g = nx.from_scipy_sparse_matrix(adj, create_using=nx.DiGraph()) orig_num_wcc = nx.number_weakly_connected_components(g) adj_tuple = sparse_to_tuple(adj) # (coords, values, shape) edges = adj_tuple[0] # List of ALL edges (either direction) edge_pairs = [(edge[0], edge[1]) for edge in edges] # store edges as list of tuples (from_node, to_node) num_test = int(np.floor(edges.shape[0] * test_frac)) # controls how large the test set should be num_val = int(np.floor(edges.shape[0] * val_frac)) # controls how alrge the validation set should be num_train = len(edge_pairs) - num_test - num_val # num train edges all_edge_set = set(edge_pairs) train_edges = set(edge_pairs) # init train_edges to have all edges test_edges = set() # init test_edges as empty set val_edges = set() # init val edges as empty set ### ---------- TRUE EDGES ---------- ### # Shuffle and iterate over all edges np.random.shuffle(edge_pairs) # get initial bridge edges bridge_edges = set(nx.bridges(nx.to_undirected(g))) if verbose: print('creating true edges...') for ind, edge in enumerate(edge_pairs): node1, node2 = edge[0], edge[1] # Recalculate bridges every ____ iterations to relatively recent if ind % 10000 == 0: bridge_edges = set(nx.bridges(nx.to_undirected(g))) # Don't sample bridge edges to increase likelihood of staying connected if (node1, node2) in bridge_edges or (node2, node1) in bridge_edges: continue # If removing edge would disconnect the graph, backtrack and move on g.remove_edge(node1, node2) if prevent_disconnect == True: if not nx.is_weakly_connected(g): g.add_edge(node1, node2) continue # Fill test_edges first if len(test_edges) < num_test: test_edges.add(edge) train_edges.remove(edge) if len(test_edges) % 10000 == 0 and verbose == True: print 'Current num test edges: ', len(test_edges) # Then, fill val_edges elif len(val_edges) < num_val: val_edges.add(edge) train_edges.remove(edge) if len(val_edges) % 10000 == 0 and verbose == True: print 'Current num val edges: ', len(val_edges) # Both edge lists full --> break loop elif len(test_edges) == num_test and len(val_edges) == num_val: break # Check that enough test/val edges were found if (len(val_edges) < num_val or len(test_edges) < num_test): print "WARNING: not enough removable edges to perform full train-test split!" print "Num. (test, val) edges requested: (", num_test, ", ", num_val, ")" print "Num. (test, val) edges returned: (", len(test_edges), ", ", len(val_edges), ")" # Print stats for largest remaining WCC print 'Num WCC: ', nx.number_weakly_connected_components(g) largest_wcc_set = max(nx.weakly_connected_components(g), key=len) largest_wcc = g.subgraph(largest_wcc_set) print 'Largest WCC num nodes: ', largest_wcc.number_of_nodes() print 'Largest WCC num edges: ', largest_wcc.number_of_edges() if prevent_disconnect == True: assert nx.number_weakly_connected_components(g) == orig_num_cc # Fraction of edges with both endpoints in largest WCC def frac_edges_in_wcc(edge_set): num_wcc_contained_edges = 0.0 num_total_edges = 0.0 for edge in edge_set: num_total_edges += 1 if edge[0] in largest_wcc_set and edge[1] in largest_wcc_set: num_wcc_contained_edges += 1 frac_in_wcc = num_wcc_contained_edges / num_total_edges return frac_in_wcc # Check what percentage of edges have both endpoints in largest WCC print 'Fraction of train edges with both endpoints in L-WCC: ', frac_edges_in_wcc(train_edges) print 'Fraction of test edges with both endpoints in L-WCC: ', frac_edges_in_wcc(test_edges) print 'Fraction of val edges with both endpoints in L-WCC: ', frac_edges_in_wcc(val_edges) # Ignore edges with endpoint not in largest WCC print 'Removing edges with either endpoint not in L-WCC from train-test split...' train_edges = {edge for edge in train_edges if edge[0] in largest_wcc_set and edge[1] in largest_wcc_set} test_edges = {edge for edge in test_edges if edge[0] in largest_wcc_set and edge[1] in largest_wcc_set} val_edges = {edge for edge in val_edges if edge[0] in largest_wcc_set and edge[1] in largest_wcc_set} ### ---------- FALSE EDGES ---------- ### # Initialize empty sets train_edges_false = set() test_edges_false = set() val_edges_false = set() # Generate candidate false edges (from g-complement) and iterate through them if false_edge_sampling == 'iterative': if verbose == True: print 'preparing complement adjacency matrix...' # Sample false edges from G-complement, instead of randomly generating edges # g_complement = nx.complement(g) adj_complement = 1 - adj.toarray() # flip 0's, 1's in adjacency matrix np.fill_diagonal(adj_complement, val=0) # set diagonals to 0 # 2 numpy arrays indicating x, y coords in adj_complement # WARNING: This line can use up a lot of RAM depending on 'adj' size idx1, idx2 = np.where(adj_complement == 1) edges_false = np.stack((idx1, idx2), axis=-1) # stack arrays into coord pairs. edge_pairs_false = [(edge[0], edge[1]) for false_edge in edges_false] # Shuffle and iterate over false edges np.random.shuffle(edge_pairs_false) if verbose == True: print 'adding candidate false edges to false edge sets...' for false_edge in edge_pairs_false: # Fill train_edges_false first if len(train_edges_false) < len(train_edges): train_edges_false.add(false_edge) if len(train_edges_false) % 100000 == 0 and verbose == True: print 'Current num false train edges: ', len(train_edges_false) # Fill test_edges_false next elif len(test_edges_false) < len(test_edges): test_edges_false.add(false_edge) if len(test_edges_false) % 100000 == 0 and verbose == True: print 'Current num false test edges: ', len(test_edges_false) # Fill val_edges_false last elif len(val_edges_false) < len(val_edges): val_edges_false.add(false_edge) if len(val_edges_false) % 100000 == 0 and verbose == True: print 'Current num false val edges: ', len(val_edges_false) # All sets filled --> break elif len(train_edges_false) == len(train_edges) and \ len(test_edges_false) == len(test_edges) and \ len(val_edges_false) == len(val_edges): break # Randomly generate false edges (idx_i, idx_j) 1 at a time to save memory elif false_edge_sampling == 'random': if verbose == True: print 'creating false test edges...' # FALSE TEST EDGES while len(test_edges_false) < len(test_edges): idx_i = np.random.randint(0, adj.shape[0]) idx_j = np.random.randint(0, adj.shape[0]) if idx_i == idx_j: # no self-loops continue # Ensure both endpoints are in largest WCC if idx_i not in largest_wcc_set or idx_j not in largest_wcc_set: continue false_edge = (idx_i, idx_j) # Make sure false_edge not an actual edge, and not a repeat if false_edge in all_edge_set: continue if false_edge in test_edges_false: continue test_edges_false.add(false_edge) if len(test_edges_false) % 100000 == 0 and verbose == True: print 'Current num false test edges: ', len(test_edges_false) # FALSE VAL EDGES if verbose == True: print 'creating false val edges...' while len(val_edges_false) < len(val_edges): idx_i = np.random.randint(0, adj.shape[0]) idx_j = np.random.randint(0, adj.shape[0]) if idx_i == idx_j: continue false_edge = (idx_i, idx_j) # Make sure false_edge in not an actual edge, not in test_edges_false, not a repeat if false_edge in all_edge_set or \ false_edge in test_edges_false or \ false_edge in val_edges_false: continue val_edges_false.add(false_edge) if len(val_edges_false) % 100000 == 0 and verbose == True: print 'Current num false val edges: ', len(val_edges_false) # FALSE TRAIN EDGES if verbose == True: print 'creating false train edges...' while len(train_edges_false) < len(train_edges): idx_i = np.random.randint(0, adj.shape[0]) idx_j = np.random.randint(0, adj.shape[0]) if idx_i == idx_j: continue false_edge = (idx_i, idx_j) # Make sure false_edge in not an actual edge, not in test_edges_false, # not in val_edges_false, not a repeat if false_edge in all_edge_set or \ false_edge in test_edges_false or \ false_edge in val_edges_false or \ false_edge in train_edges_false: continue train_edges_false.add(false_edge) if len(train_edges_false) % 100000 == 0 and verbose == True: print 'Current num false train edges: ', len(train_edges_false) ### ---------- FINAL DISJOINTNESS CHECKS ---------- ### if verbose == True: print 'final checks for disjointness...' # assert: false_edges are actually false (not in all_edge_tuples) assert test_edges_false.isdisjoint(all_edge_set) assert val_edges_false.isdisjoint(all_edge_set) assert train_edges_false.isdisjoint(all_edge_set) # assert: test, val, train false edges disjoint assert test_edges_false.isdisjoint(val_edges_false) assert test_edges_false.isdisjoint(train_edges_false) assert val_edges_false.isdisjoint(train_edges_false) # assert: test, val, train positive edges disjoint assert val_edges.isdisjoint(train_edges) assert test_edges.isdisjoint(train_edges) assert val_edges.isdisjoint(test_edges) if verbose == True: print 'creating adj_train...' # Re-build adj matrix using remaining graph adj_train = nx.adjacency_matrix(g) # Convert edge-lists to numpy arrays train_edges = np.array([list(edge_tuple) for edge_tuple in train_edges]) train_edges_false = np.array([list(edge_tuple) for edge_tuple in train_edges_false]) val_edges = np.array([list(edge_tuple) for edge_tuple in val_edges]) val_edges_false = np.array([list(edge_tuple) for edge_tuple in val_edges_false]) test_edges = np.array([list(edge_tuple) for edge_tuple in test_edges]) test_edges_false = np.array([list(edge_tuple) for edge_tuple in test_edges_false]) if verbose == True: print 'Done with train-test split!' print 'Num train edges (true, false): (', train_edges.shape[0], ', ', train_edges_false.shape[0], ')' print 'Num test edges (true, false): (', test_edges.shape[0], ', ', test_edges_false.shape[0], ')' print 'Num val edges (true, false): (', val_edges.shape[0], ', ', val_edges_false.shape[0], ')' print '' # Return final edge lists (edges can go either direction!) return adj_train, train_edges, train_edges_false, \ val_edges, val_edges_false, test_edges, test_edges_false
#!/usr/bin/env python import networkx as nx G = nx.Graph() G.add_edge("a", "b") G.add_edge("b", "c") G.add_edge("a", "c") G.add_edge("c", "d") G.add_edge("d", "e") G.add_edge("d", "f") G.add_edge("e", "f") print list(nx.bridges(G))