def would_cause_cycle(e, u, v, reverse=False): """ Test if adding the edge u -> v to the BayesNet object would create a DIRECTED (i.e. illegal) cycle. """ G = nx.DiGraph(e) if reverse: G.remove_edge(v, u) G.add_edge(u, v) try: nx.find_cycle(G, source=u) return True except: return False
def test_prev_explored(self): # https://github.com/networkx/networkx/issues/2323 G = nx.DiGraph() G.add_edges_from([(1,0), (2,0), (1,2), (2,1)]) assert_raises(nx.exception.NetworkXNoCycle, find_cycle, G, source=0) x = list(nx.find_cycle(G, 1)) x_ = [(1, 2), (2, 1)] assert_equal(x, x_) x = list(nx.find_cycle(G, 2)) x_ = [(2, 1), (1, 2)] assert_equal(x, x_)
def build_clusters(objects, relations, styles_by_type): """ Return a graph whose vertices are names of objects mapping to clusters, edges represent direct containment of clusters and every cluster is directly contained in at most one parent cluster. Raises `GraphError` if such a graph cannot be built. """ result = nx.DiGraph() for o in objects: if o.type in styles_by_type.get('cluster-type', set()): result.add_node(o.name, {'type': o.type, 'attrs': o.attrs.asDict()}) result.add_edges_from( (r.lhs, r.rhs) for r in relations if r.rel in styles_by_type.get('containment', set()) and r.lhs in result and r.rhs in result) try: cycle = nx.find_cycle(result) except nx.exception.NetworkXNoCycle: pass else: raise GraphError('Circular containment: %s in %s' % (cycle[0][0], ' in '.join(v for u, v in cycle))) transitive_reduce(result) for v in result: out_edges = result.out_edges(v) if len(out_edges) > 1: raise GraphError('Cluster %s in more than one parent: %s' % (v, ', '.join(v for _, v in out_edges))) return result
def _insert_after(self, graph, route, other): try: route_successors = graph.successors(route.name) except nx.NetworkXError: route_successors = [] if other in route_successors: graph.add_edge(other, route.name) raise DependencyLoop(nx.find_cycle(graph, route.name)) try: other_successors = graph.successors(other)[:] except nx.NetworkXError: other_successors = [] for other_successor in other_successors: if self.routes[other_successor].urltpl < route.urltpl: try: self._insert_after(graph, route, other_successor) break except DependencyLoop: pass else: graph.add_edge(other, route.name) for other_successor in graph.successors(other)[:]: if route.urltpl < self.routes[other_successor].urltpl: try: graph.remove_edge(other, other_successor) except nx.NetworkXError: pass else: graph.add_edge(route.name, other_successor)
def sorted_routes(self): graph = nx.DiGraph() constrained = set(r for r in self.routes.values() if r.before or r.after) unconstrained = set(self.routes.values()) - constrained for r1, r2 in permutations(unconstrained, 2): if r1.urltpl.equals(r2.urltpl): continue if r1.urltpl < r2.urltpl: graph.add_edge(r1.name, r2.name) else: graph.add_edge(r2.name, r1.name) for route in constrained: self._insert_constrained(graph, route) for route in unconstrained: if not graph.has_node(route.name): # quite improbable case, but this scenario does exist (all # routes unconstrained and equal, for example) graph.add_edge(None, route.name) try: loop = nx.find_cycle(graph) raise DependencyLoop(loop) except nx.NetworkXNoCycle: pass return list(self.routes[n] for n in nx.topological_sort(graph) if n is not None)
def concave_hull(polydata): """extract the concave hull of a vtk polydata object""" # setup the extraction pipeline extract = tvtk.FeatureEdges() # we're only interested in the boundaries extract.feature_edges = False extract.boundary_edges = True extract.manifold_edges = False extract.non_manifold_edges = False configure_input(extract, polydata) # compute edges extract.update() # extract the points points = extract.output.points.to_array() # slice every 2nd and 3rd point line_ids = np.c_[ extract.output.lines.to_array()[1::3], extract.output.lines.to_array()[2::3] ] # 1st points should all be 2 assert (extract.output.lines.to_array()[0::3] == 2).all(), "expected only lines" # construct a directed graph D = networkx.DiGraph(data=line_ids.tolist()) # find the first cycle first_cycle = networkx.find_cycle(D) # create the index to lookup points, including last point cycle = [x[0] for x in first_cycle] + [first_cycle[0][0]] # fill in index and return first 2 coordinates return points[cycle, :2]
def analyse_cyclic_dependencies(graph): try: cycle = networkx.find_cycle(graph) dependency_string = ' => '.join("[%s is referenced by %s]" % tup for tup in cycle) raise CyclicDependencyException("Found cyclic dependency between stacks: {0}".format(dependency_string)) except NetworkXNoCycle: pass
def orient_undecided_edges(self): vertices = self.states_df.columns nx_graph = self.new_filled_nx_graph() undecided_edges = [] for vtx in vertices: nbor_set = set(self.vtx_to_nbors[vtx]) - \ set(nx.all_neighbors(nx_graph, vtx)) for nbor in nbor_set: undecided_edges.append((vtx, nbor)) for beg_vtx, end_vtx in undecided_edges: # add dir_edge to nx_graph in one direction # and see if it causes cycle # If it doesn't, then # add dir edge to vtx_to_parents in same direction # and if it does add to vtx_to_parents in opposite direction nx_graph.add_edge(beg_vtx, end_vtx) try: cycle_edge_list = nx.find_cycle(nx_graph, source=beg_vtx) except nx.exception.NetworkXNoCycle: cycle_edge_list = [] if len(cycle_edge_list) == 0: self.vtx_to_parents[end_vtx].append(beg_vtx) else: self.vtx_to_parents[beg_vtx].append(end_vtx) # restore nx_graph to original state nx_graph.remove_edge(beg_vtx, end_vtx)
def get_cycles(self): """Returns a list of cycles in the dependency graph, if they are present.""" cycles = None try: cycles = nx.find_cycle(self._dependency_graph) except Exception: pass return cycles
def add_edge(self, u, v, t): # add an edge. if it creates a cycle, remove the oldest edge in the cycle super(TimelyForest, self).add_edge(u=u, v=v, t=t) try: cycle = nx.find_cycle(self, orientation='ignore') except NetworkXNoCycle: cycle = None if cycle: # go through costly remove only if necessary. return self.remove_oldest_edge(t, cycle) return None
def orient_undecided_edges(self): """ When this function is called in learn_str(), the vtx_to_parents that has been learned so far may not include all of the edges implied by vtx_to_nbors. Hence, there might still be some undirected edges. This function uses a reasonable but not rigorous heuristic to orient those undecided edges. Returns ------- None """ if self.verbose: print('\nbegin orient_undecided_edges') vertices = self.states_df.columns nx_graph = self.new_filled_nx_graph() undecided_edges = [] for vtx in vertices: nbor_set = set(self.vtx_to_nbors[vtx]) - \ set(nx.all_neighbors(nx_graph, vtx)) for nbor in nbor_set: if (nbor, vtx) not in undecided_edges: undecided_edges.append((vtx, nbor)) for beg_vtx, end_vtx in undecided_edges: # add dir_edge to nx_graph in one direction # and see if it causes cycle # If it doesn't, then # add dir edge to vtx_to_parents in same direction # and if it does add to vtx_to_parents in opposite direction nx_graph.add_edge(beg_vtx, end_vtx) try: cycle_edge_list = nx.find_cycle(nx_graph, source=beg_vtx) except nx.exception.NetworkXNoCycle: cycle_edge_list = [] if len(cycle_edge_list) == 0: self.vtx_to_parents[end_vtx].append(beg_vtx) else: self.vtx_to_parents[beg_vtx].append(end_vtx) # restore nx_graph to original state nx_graph.remove_edge(beg_vtx, end_vtx) if self.verbose: print('undecided edges=', undecided_edges) print('vtx_to_parents=') pp.pprint(self.vtx_to_parents, width=1) print('end orient_undecided_edges')
def main(): verbose = False db = connect_to_mysql(Config.mysql_conf_file) cursor = db.cursor() switch_to_db(cursor, 'icgc') # are there children with multiple parents? Yes. So I need some kind of # directed graph, rather tha a tree. qry = "select child, count(distinct parent) as ct from reactome_hierarchy " qry += "group by child having ct>1" ret = search_db(cursor, qry) print("number of children with multiple parents:", len(ret)) # feed the parent/child pairs as edges into graph ret = hard_landing_search(cursor, 'select parent, child from reactome_hierarchy') graph = nx.DiGraph(ret) # directed graph print("graph is directed: ", graph.is_directed()) print("number of edges:", len(graph.edges)) print("graph is multigraph:", graph.is_multigraph()) try: edges = nx.find_cycle(graph) except: print("hooray, no cycles found") # graph.in_degree is a list of pairs, rather than a method # candidate roots zero_in_degee_nodes = [name for name, indegree in graph.in_degree if indegree==0] node_id_string = ",".join([quotify(z) for z in zero_in_degee_nodes]) qry_template = "select * from reactome_pathways where reactome_pathway_id in (%s)" root_names = hard_landing_search(cursor, qry_template% node_id_string) gene_groups = {} for pthwy_id, name in root_names: if "disease" in name.lower(): continue if verbose: print(pthwy_id, name) characterize_subtree(cursor, graph, pthwy_id, gene_groups, 1, verbose=verbose) cursor.close() db.close() # print("\n===========================") # for group, genes in gene_groups.items(): # print (group, len(genes)) hist_plot(gene_groups)
def order_build(graph): ''' Assumes that packages are in graph. Builds a temporary graph of relevant nodes and returns it topological sort. Relevant nodes selected in a breadth first traversal sourced at each pkg in packages. ''' reorder_cyclical_test_dependencies(graph) try: order = list(nx.topological_sort(graph)) order.reverse() except nx.exception.NetworkXUnfeasible: raise ValueError("Cycles detected in graph: %s", nx.find_cycle(graph, orientation='reverse')) return order
def cycle_check(parents, ik_map): g = make_graph(parents) test = nx.DiGraph() test.add_nodes_from([i for i in range(len(ik_map))]) parents = [ik_map[i[0]][0] for i in g.tolist()] children = [ik_map[i[1]][0] for i in g.tolist()] for i in range(len(parents)): test.add_edge(parents[i], children[i]) try: cycle = list(nx.find_cycle(test, orientation='original')) except: cycle = [] return cycle
def cycles(self) -> Optional[List[int]]: """Returns cycles in neuron if any. See also -------- networkx.find_cycles() Function used to find cycles. """ try: c = nx.find_cycle( self.graph, source=self.nodes[self.nodes.type == 'end'].node_id.values) return c except nx.exception.NetworkXNoCycle: return None except BaseException: raise
def is_stratified(self): ''' Checks if the logic program can be stratified. :return: bool: True if the program can be stratified. False if not. ''' G = self.graph try: cycle = nx.find_cycle(G) for edge in cycle: source = edge[0] target = edge[1] data = G.get_edge_data(source, target) negated = data[0]['negated'] if negated: return False except nx.NetworkXNoCycle: pass return True
def check_loops(gltf: GLTF): n = DiGraph() all_nodes = list(range(len(gltf.model.nodes))) for i in all_nodes: n.add_node(i) for node_index, node in enumerate(gltf.model.nodes): if node.children: for c in node.children: n.add_edge(node_index, c) try: c = find_cycle(n) except NetworkXNoCycle: pass else: logger.info(c=c) raise ZValueError("cycle found", c=c)
def get_all_cycles(breakpoint_graph): visited = set() cycles = [] for vertex in breakpoint_graph.nodes(): if vertex in visited: continue try: cycle = nx.find_cycle(breakpoint_graph.bg, vertex) new = False for v1, v2, dir in cycle: if v1 not in visited: new = True visited.add(v1) if new: cycles.append(cycle) except: pass return cycles
def print_cycle_info_and_break_cycles(table_graph: Any) -> None: """Change given graph by breaking cycles.""" simple_cycles = list(nx.simple_cycles(table_graph)) if len(simple_cycles) > 0: print("\n%s self-references and simple cycles found:" % (len(simple_cycles), )) print(simple_cycles) # Break simple cycles and self-references to help find bigger cycles copy_of_graph = table_graph.copy() db_graph.break_cycles(copy_of_graph) try: cycle = nx.find_cycle(copy_of_graph) print("\nAnother cycle was detected:") print(cycle) except nx.exception.NetworkXNoCycle: pass
def get_substructures(Gn): subs = set() for G in Gn: degrees = list(dict(G.degree()).values()) if any(i == 2 for i in degrees): subs.add('linear') if np.amax(degrees) >= 3: subs.add('non linear') if 'linear' in subs and 'non linear' in subs: break if is_directed(Gn): for G in Gn: if len(list(nx.find_cycle(G))) > 0: subs.add('cyclic') break return subs
def min_cycle_ratio(G: nx.Graph, dist): """[summary] todo: parameterize cost and time Arguments: G ([type]): [description] Returns: [type]: [description] """ mu = 'cost' sigma = 'time' set_default(G, mu, 1) set_default(G, sigma, 1) T = type(dist[next(iter(G))]) def calc_weight(r, e): """[summary] Arguments: r ([type]): [description] e ([type]): [description] Returns: [type]: [description] """ u, v = e return G[u][v]['cost'] - r * G[u][v]['time'] def calc_ratio(C): """Calculate the ratio of the cycle Arguments: C {list}: cycle list Returns: cycle ratio """ total_cost = sum(G[u][v]['cost'] for (u, v) in C) total_time = sum(G[u][v]['time'] for (u, v) in C) return T(total_cost) / total_time C0 = nx.find_cycle(G) r0 = calc_ratio(C0) return max_parametric(G, r0, C0, calc_weight, calc_ratio, dist)
def random_algorithm(input_graph): G = input_graph.copy() cycle_list = [] pre_penalty = 0 while G.nodes(): try: edge_cycle = nx.find_cycle(G) vertex_cycle = [] for edge in edge_cycle: vertex_cycle.append(edge[0]) pre_penalty += G.node[edge[0]]['penalty'] G.remove_node(edge[0]) cycle_list.append(vertex_cycle) except: print("No cycle found") break penalty = find_total_penalty(input_graph) - pre_penalty formatted_cycle_list = format_output_cycles(cycle_list) return [formatted_cycle_list, penalty]
def Hv_rule4(G, Hv, N2, k, solution, permanent): try: cycle = nx.find_cycle(Hv, source=None, orientation='ignore') if len(cycle) % 2 == 0: #print("rule4") cycle_nodes = set() for edge in cycle: cycle_nodes.add(edge[0]) cycle_nodes.add(edge[1]) N2_cycle = list(cycle_nodes & set(N2)) #print(N2_cycle) G1 = copy.deepcopy(G) G1.remove_nodes_from(N2_cycle) return branching(G1, k - len(N2_cycle), solution + N2_cycle, permanent) else: return False except: return False
def has_cycle(graph: networkx.DiGraph) -> bool: """ Checks that a graph does not contain a cycle. :param graph: The graph to check :return: A boolean true if there is a cycle. """ sources = find_source_nodes(graph) if not sources: return True for source in sources: try: cycle = networkx.find_cycle(graph, source) if cycle: print(cycle) return True except networkx.NetworkXNoCycle: return False return False
def maximum_tree(G, root=0, step=0): """ :param G: graph of type networkx Graph :param root: the root node :param step: this function being recursive, the step tells us how deep we are with the recursion. :return: a maximum spanning tree of the graph G, of type network Graph. """ G = prepare(G, root) P = greedy(G, root) if nx.is_arborescence(P): return P else: # there is a cycle C = nx.find_cycle(P, orientation='ignore') G, dictionary_cleanup = cleanup(G, root) G_contracted, dictionary = contract(G, C, root=root, step=step) T_contracted = maximum_tree(G_contracted, root=root, step=step + 1) T_expanded = expand(T_contracted, C, dictionary, root=root, step=step) T_expanded = uncleanup(T_expanded, dictionary_cleanup, root=root) return T_expanded
def exchange_shifts(workers: List[Worker]): while workers: G = nx.DiGraph() G = build_graph(workers) # find the cycle in the graph changes = list(nx.find_cycle(G, orientation='ignore')) # [(3, 'c', 'forward')] for change in changes: if (type(change[0]) == str): currentShift = find_shift(workers, change[0]) print( str(change[0]) + " moves from shift " + str(currentShift) + " to Shift " + str(change[1])) #remove worker workers = update_workers(workers, change[0]) #remove this shift from al preferances update_preferances(workers, change[1])
def add_edges_in_order(edge_to_win_ratio, vote_set): """Adds edges in order of weight, never adding edges that would create a cycle.""" win_graph = nx.DiGraph() ordered_votes = sorted(vote_set, key=lambda e: edge_to_win_ratio[(e[0], e[1])], reverse=True) for c1, c2, result in ordered_votes: try: win_graph.add_edge(c1, c2) cycles = nx.find_cycle(win_graph) # If we hit this line, a NoCycle exception was not thrown, therefore there is a cycle and we have to # remove an edge from it win_graph.remove_edge(c1, c2) except nx.NetworkXNoCycle: continue assert nx.is_directed_acyclic_graph(win_graph) return win_graph
def augmenting_path(G, demand_nodes, assignments): reduced_elements = 0 while 1: try: cycle = nx.find_cycle( G) #Done arbitrarily. Maybe better to select one specifically? reduced_elements += adjust_graph(G, cycle, demand_nodes, assignments) print("Cycle: " + str(cycle)) except nx.NetworkXNoCycle: break for i in G.nodes(): # Done arbitrarily. Maybe select one specifically? if G.degree(i) == 1: path = list(nx.dfs_edges(G, source=i)) print("Path " + str(path)) reduced_elements += adjust_graph(G, path, demand_nodes, assignments) break return reduced_elements
def requestLockOrder(self, order): 'verify that the requested lock order wont cause deadlocks' if len(order) == 1: return True links = [] for od in self.orders: links.extend(list(zip(od, od[1:]))) links.extend(list(zip(order, order[1:]))) graph = nx.DiGraph(links) try: loops = nx.find_cycle(graph) except: loops = [] if len(loops) > 0: return False self.orders.append(order) return True
def approximate_steiner(graph, terminals): steiner_tree = nx.Graph() num_terminals = len(terminals) all_terminal_paths = list() for i in range(0, num_terminals): for j in range(i + 1, num_terminals): paths = get_paths(graph, terminals[i], terminals[j]) least_cost_path, least_cost = get_least_cost_path(graph, paths) path = dict() path['cost'] = least_cost path['path'] = least_cost_path print "Path" + str(path['path']) all_terminal_paths.append(path) all_terminal_paths.sort(key=lambda x: x['cost']) for t_path in all_terminal_paths: steiner_tree.add_path(t_path['path']) if check_terminals_connected(steiner_tree, terminals): break conn_components = list(comp.connected_components(steiner_tree)) while len(conn_components) > 1: comp1 = conn_components[0] comp2 = conn_components[1] for j in range(0, len(comp1)): for k in range(0, len(comp2)): if graph.has_edge(comp1[j], comp2[k]): steiner_tree.add_edge(comp1[j], comp2[k]) break conn_components = list(comp.connected_components(steiner_tree)) while True: try: cycle = nx.find_cycle(steiner_tree) print('Cycle found') edge = cycle[0] steiner_tree.remove_edge(edge[0], edge[1]) except: break weights = nx.get_node_attributes(graph, 'weight') steiner_cost = 0 for node in list(steiner_tree.nodes): steiner_cost = steiner_cost + weights[node] return steiner_tree, steiner_cost
def optimize_cycle_remover(solver, tree, cycle_killer_fn, orig_cost): if not orig_cost: orig_cost = average_pairwise_distance(tree) tree_set = set(tree.nodes) candidates = [ (v, list(set(solver.neighbors(v)) & tree_set)) for v in solver.G if solver.is_optional(v) and len(set(solver.neighbors(v)) & tree_set) > 2 ] # Candidates contains all vertices with >2 neighbors in tree and list of all those neighboring vertices min_cost = orig_cost for pair in candidates: v = pair[0] edges = [(v, x) for x in pair[1] if weight(solver.G, (v, x)) < solver.max_T_edge_weight] if len(edges) < 2: continue edges.sort(key=lambda x: weight(solver.G, x)) # Try adding a vertex and two edges to tree to make a cycle and delete min edge added_edge = False min_edge = edges[0] solver.add_edge(min_edge) for j in range(1, len(edges)): solver.add_edge(edges[j]) cycle: list = find_cycle(tree, v) replaced_edge, new_cost = cycle_killer_fn(solver, cycle, orig_cost=min_cost) if replaced_edge: added_edge = True # print("Added vertex", v, "and edges:", min_edge, edges[j]) # print("Prev cost:", min_cost) # print("New cost:", new_cost) min_cost = new_cost solver.remove_edge(replaced_edge) else: solver.remove_edge(edges[j]) if not added_edge: solver.remove_edge(min_edge) return min_cost
def __init__(self, structure: StructureModel): """ Create a ``BayesianNetwork`` with a DAG defined by ``StructureModel``. Args: structure: a graph representing a causal relationship between variables. In the structure - cycles are not allowed; - multiple (parallel) edges are not allowed; - isolated nodes and multiple components are not allowed. Raises: ValueError: If the structure is not a connected DAG. """ n_components = nx.number_weakly_connected_components(structure) if n_components > 1: raise ValueError( "The given structure has {n_components} separated graph components. " "Please make sure it has only one.".format(n_components=n_components) ) if not nx.is_directed_acyclic_graph(structure): cycle = nx.find_cycle(structure) raise ValueError( "The given structure is not acyclic. Please review the following cycle: {cycle}".format( cycle=cycle ) ) # _node_states is a Dict in the form `dict: {node: dict: {state: index}}`. # Underlying libraries expect all states to be integers from zero, and # thus this dict is used to convert from state -> idx, and then back from idx -> state as required self._node_states = None # type: Dict[str: Dict[Hashable, int]] self._structure = structure # _model is a pgmpy Bayesian Model. # It is used for: # - probability fitting # - predictions self._model = BayesianModel() self._model.add_edges_from(structure.edges)
def _acyclics_subgraphs(self, G): """ Divide a graph into connected components subgraphs Divide a graph into connected components subgraphs and remove its cycles removing the edge with higher weight inside the cycle. Also prune the graphs by number of nodes in case the graph has not enought nodes. Args: G (nx.Graph): Graph Returns: list(nx.Graph): Returns a list of graphs which are subgraphs of G with cycles removed. """ if not isinstance(G, nx.Graph): raise TypeError('G must be a nx.Graph instance') S = [] # List of subgraphs of G for c in nx.connected_components(G): g = G.subgraph(c).copy() # Remove all cycles that we may find has_cycles = True while has_cycles: try: cycle = nx.find_cycle(g) weights = np.asarray([G[u][v]['weight'] for u, v in cycle]) idx = weights.argmax() # Remove the edge with highest weight at cycle g.remove_edge(*cycle[idx]) except nx.NetworkXNoCycle: has_cycles = False if len(g) < self.min_nb_nodes: # Prune small subgraphs logging.verbose( 'Remove a small line with {} nodes'.format(len(g)), 1) continue S.append(g) return S
def would_create_cycle(self, move): """ This function performs the move 'move' on self.nx_graph and then tests to see if the new graph has cycles. It communicates the result of the tests in the bool output. It restores nx_graph to its original state after the testing for cycles is concluded. Parameters ---------- move : tuple[str, str, str] Returns ------- bool """ (beg_vtx, end_vtx, action) = move if action == 'del': return False if action == 'add': self.nx_graph.add_edge(beg_vtx, end_vtx) elif action == 'rev': self.nx_graph.remove_edge(beg_vtx, end_vtx) self.nx_graph.add_edge(end_vtx, beg_vtx) else: assert False try: cycle_edge_list = nx.find_cycle(self.nx_graph, source=beg_vtx) except nx.exception.NetworkXNoCycle: cycle_edge_list = [] # restore self.nx_graph to original state if action == 'add': self.nx_graph.remove_edge(beg_vtx, end_vtx) elif action == 'rev': self.nx_graph.add_edge(beg_vtx, end_vtx) self.nx_graph.remove_edge(end_vtx, beg_vtx) return len(cycle_edge_list) > 0
def __init__(self, workflow): log.info(f'Building workflow graph for {workflow}...') self.workflow = workflow self.G = nx.DiGraph() self.nodes = self.G.nodes self.edges = self.G.edges for name, task in workflow.tasks.items(): self.G.add_node(name) for name, task in workflow.tasks.items(): try: self._make_edges(task) except ValueError as e: err = f'While adding edges for: {task}\n{e}' raise ValueError(err) from None if not nx.is_directed_acyclic_graph(self.G): cycles = nx.find_cycle(self.G) raise ValueError(f'Not a DAG! Possible causes:{list(cycles)}')
def find_watercycles(self, n): cycles_ = [ self.waternet.subgraph(cycle) for cycle in nx.cycle_basis(self.waternet) if len(cycle) == n ] waterdict = { node[0]: node[1] for node in self.waternet.nodes(data=True) } watercycles = [] for cycle_ in cycles_: edges = [(node1, node2, self.waternet.get_edge_data(node1, node2)) for node1, node2 in nx.find_cycle(cycle_)] watercycle = Cycle(edges=edges, nodes=waterdict) # nx.set_node_attributes(watercycle, waterdict) watercycles.append(watercycle) return watercycles
def is_cyclic(self): """ Checks for combinational loops in circuit Returns ------- Bool Existence of cycle """ g = self.graph.copy() g.remove_edges_from( (e, s) for s in self.startpoints() for e in self.endpoints() ) try: if nx.find_cycle(g): return True except NetworkXNoCycle: pass return False
def break_cycles(edges): '''Break any graph cycles present in the list of edges''' dig = networkx.digraph.DiGraph() for src, dest in edges: dig.add_edge(src, dest) while True: try: cycle = networkx.find_cycle(dig) except networkx.NetworkXNoCycle: break src, dest = cycle[-1] logger.warning('Found cycles in port graph: %s; breaking at %s->%s', cycle, src, dest) dig.remove_edge(src, dest) edges.remove((src, dest)) return edges
def check_for_cycles(self): """check for cycles Raise: ConfigurationError if cycles found """ cycles = None try: cycles = nx.find_cycle(self.G2) logging.info("cycles:" + str(cycles)) except nx.exception.NetworkXNoCycle as e: # it throws an error if there are no cycles, the opposite of what we want if str(e) != "No cycle found.": raise e # pragma: no cover else: logging.info("OK: no cycles found") # to get here, we must have cycles! if cycles: raise ConfigurationError("Cycle(s) found: %s" % str(cycles))
def cycle_subtourelim(model, where): ''' Find the components of the graph Select the smallest components (number of vertices) Force the model to have at least one edge connecting the component to its complement ''' if where == GRB.Callback.MIPSOL: G = nx.Graph() edges = [ edge.vertices for edge in model._edges if model.cbGetSolution(model._edgevar[edge.vertices]) ] G.add_edges_from(edges) cycle = nx.find_cycle(G) lhs = quicksum(model._edgevar[vertex1.incident[vertex2].vertices] for vertex1, vertex2 in cycle) rhs = len(cycle) - 1 model.cbLazy(lhs <= rhs)
def removeCycles(cls, inGraph): diGraph = inGraph.copy() while not nx.is_directed_acyclic_graph(diGraph): cycle = nx.find_cycle(diGraph) weakestLink = sys.float_info.max weakestEdge = None for edge in cycle: weight = diGraph[edge[0]][edge[1]]['covweight'] if weight < weakestLink: weakestEdge = edge weakestLink = weight diGraph.remove_edge(weakestEdge[0], weakestEdge[1]) return diGraph
def DMP(g): v = g.number_of_nodes() e = g.number_of_edges() h = networkx.Graph() h.add_edges_from(networkx.find_cycle(g)) b = [] b.append((h.copy())) b.append((h.copy())) #Handles trivial cases if (v < 5): planar() if (3 * v - 6 < e): nonplanar() if (h is None): planar() #Upper bound determined by Euler's Formula f = e - v + 2 for r in range(0, e - v): add_face(g, h, b) planar()
def find_small_component(graph, graph_name): """ graph에서 작은 component를 찾고 node / edge와 cycle이 있는지 찾는다. """ S = [ graph.subgraph(c).copy() for c in sorted(nx.connected_components(graph), key=len, reverse=True) ] for i, subG in enumerate(S): try: print("Subgraph of {0} : node : {1}, edge : {2}, has cycle : {3}". format( graph_name, nx.number_of_nodes(subG), nx.number_of_edges(subG), True if len(nx.find_cycle(subG, orientation="original")) > 0 else False)) except Exception as e: print("Subgraph of {0} : node : {1}, edge : {2}, has cycle : {3}". format(graph_name, nx.number_of_nodes(subG), nx.number_of_edges(subG), False))
def pop_cycle_segments(graph): """ Find all cycles in the given nx.Graph (each cycle becomes a 'segment'), and remove the cycle nodes from the graph after they are found. """ segments = [] try: while True: cycle_edges = nx.find_cycle(graph) graph.remove_edges_from(cycle_edges) cycle_nodes = [node[0] for node in cycle_edges] cycle_nodes.append(cycle_edges[-1][1]) # Drop nodes without neighbors for node in cycle_nodes[:-1]: if not graph.neighbors(node): graph.remove_node(node) segments.append(cycle_nodes) except nx.NetworkXNoCycle: pass return segments
def compute(problem): problem.set_edges_and_vertices() net_graph = nx.DiGraph() net_graph.add_edges_from(problem.edges) temp = list() while True: try: this = [] cycle = nx.find_cycle(net_graph) for pair in cycle: if pair[0] not in this: this.append(pair[0]) if pair[1] not in this: this.append(pair[1]) net_graph.remove_nodes_from(this) if len(cycle) < 5: temp.append(this) except Exception, e: new_copy = [] for donor_cycle in temp: new_temp = [str(i) for i in donor_cycle] new_copy.append(new_temp) final_copy = "" for donor_cycle in new_copy: donor_string = " ".join(donor_cycle) new_string = donor_string.rstrip() new_string += "; " final_copy += new_string problem.solution = final_copy return
def constrained_birkhoff_von_neumann_iterator(H, X): (G, p) = H.pop(0) #remove edges with integer weights #extracts all edges satisfy the weight threshold: eligible_edges = [(from_node,to_node,edge_attributes) for from_node,to_node,edge_attributes in G.edges(data=True) if all(i < edge_attributes['weight'] or edge_attributes['weight'] < i for i in range(0,int(math.floor(sum(sum(X)))+1)))] if not eligible_edges: return(H) else: K = nx.DiGraph() K.add_edges_from(eligible_edges) #find a cycle and compute the push_forward and push_reverse probabilities and graphs cycle = nx.find_cycle(K, orientation='ignore') forward_weights = [(d['weight'],d['min_capacity'],d['max_capacity']) for (u,v,d) in K.edges(data=True) if (u,v,'forward') in cycle] reverse_weights = [(d['weight'],d['min_capacity'],d['max_capacity']) for (u,v,d) in K.edges(data=True) if (u,v,'reverse') in cycle] push_forward = min([x[2] - x[0] for x in forward_weights]) push_reverse = min([x[2] - x[0] for x in reverse_weights]) pull_forward = min([x[0] - x[1] for x in forward_weights]) pull_reverse = min([x[0] - x[1] for x in reverse_weights]) push_forward_pull_reverse = min(push_forward,pull_reverse) push_reverse_pull_forward = min(pull_forward,push_reverse) #Construct the push_forward_pull_reverse graph G1 = copy.deepcopy(G) for (u,v,d) in G1.edges(data=True): if (u,v,'forward') in cycle: d['weight']+=push_forward_pull_reverse if (u,v,'reverse') in cycle: d['weight']+=-push_forward_pull_reverse #Construct the push_reverse_pull_forward graph G2 = copy.deepcopy(G) for (u,v,d) in G2.edges(data=True): if (u,v,'reverse') in cycle: d['weight']+=push_reverse_pull_forward if (u,v,'forward') in cycle: d['weight']+=-push_reverse_pull_forward gamma = min([1,max([0,push_reverse_pull_forward/(push_forward_pull_reverse + push_reverse_pull_forward)])]) return([(G1,p*gamma), (G2,p*(1-gamma))])
def update_jamstarts(self): concert = self.video.concert relevant_edges_query = Q(confidence__gt=settings.CONFIDENCE_THRESHOLD) & Q(video1__concert_id=concert.id) & Q(video2__concert_id=concert.id) acyclic_edges_query = Q(video1__is_cycle=False) & Q(video2__is_cycle=False) acyclic_relevant_edges = Edge.objects.filter(relevant_edges_query & acyclic_edges_query) # unique the resulting edges and make all edges positive digraph_edges = [] seen_video_ids = set() for edge in acyclic_relevant_edges: video_ids = (edge.video1_id, edge.video2_id) if video_ids in seen_video_ids or video_ids[0] == video_ids[1]: continue else: seen_video_ids.add(video_ids) # if the edge is negative, flip it! We only want positive edges if edge.offset < 0: edge.offset *= -1 edge.video1_id, edge.video2_id = edge.video2_id, edge.video1_id edge_data = (int(edge.video2_id), int(edge.video1_id), edge.offset) digraph_edges.append(edge_data) if len(digraph_edges) == 0: # if there are no edges, then we just have to create a jamjar w/ one video (this one) in it new_start_id = self.video.id else: # build a graph from the resulting edges digraph = nx.DiGraph() video_id = int(self.video.id) digraph.add_node(video_id) digraph.add_weighted_edges_from(digraph_edges) # find all videos in the subgraph undirected_graph = digraph.to_undirected() video_ids_in_subgraph = nx.node_connected_component(undirected_graph, video_id) # check if a cycle exists -- if so: f**k this video # if not: continue as normal try: cycle = nx.find_cycle(digraph) # if we get here, a cycle exists, so f**k this video new_start_id = self.video.id # mark this jamstart as being in a cycle self.video.is_cycle = True except nx.NetworkXNoCycle: # sort the directed graph such that if A has an edge to B, A will come before B in the resulting list temporally_sorted_videos = nx.topological_sort(digraph) # the first video id in the list is the jamstart for this subgraph new_start_id = temporally_sorted_videos[0] # update start_id for all videos in the resulting subgraph JamJarMap.objects.filter(video_id__in=video_ids_in_subgraph).update(start_id=new_start_id) # And add this one JamJarMap.objects.create(video=self.video, start_id=new_start_id)
def group_substructures(mols, patterns=None, mol_instantiator=unsanitized_mol_from_smiles, pattern_instantiator=mol_from_smarts, matcher=has_query_query_match, reduce=True): import networkx as nx # Instantiate mols and their "pattern" representation # Must document that, when already provided Chem.Mol objects, instantiators usually are no-ops if pattern_instantiator is not None: patterns = list(to_rdkit_mols(mols, pattern_instantiator)) if mol_instantiator is not None: mols = list(to_rdkit_mols(mols, mol_instantiator)) if patterns is None: patterns = mols # Sort substructures by decreasing number of atoms num_atoms = [mol.GetNumAtoms() for mol in mols] descending_number_of_atoms_order = np.argsort(num_atoms)[::-1] representative = [None] * len(mols) # For duplicates graph = nx.DiGraph() # Directed graph, if (p1, p2) on it, # Nasty stuff that would not happen if cheminformatics were logical # noinspection PyUnusedLocal has_equal_nonequal = has_cycles = False for p1, p2 in combinations(descending_number_of_atoms_order, 2): p2_in_p1, p1_in_p2 = matcher(mols[p1], patterns[p2]), matcher(mols[p2], patterns[p1]) representative[p1] = representative[p1] or p1 representative[p2] = representative[p2] or p2 if p2_in_p1 and p1_in_p2: representative[p2] = representative[p1] elif p2_in_p1: if num_atoms[p1] == num_atoms[p2] and not has_equal_nonequal: has_equal_nonequal = True info('mindblowingly, with equal number of atoms, one contains the other but not viceversa') graph.add_edge(representative[p1], representative[p2]) elif p1_in_p2: if num_atoms[p1] == num_atoms[p2] and not has_equal_nonequal: has_equal_nonequal = True info('mindblowingly, with equal number of atoms, one contains the other but not viceversa') graph.add_edge(representative[p2], representative[p1]) else: graph.add_node(representative[p1]) graph.add_node(representative[p2]) # Cycles? try: nx.find_cycle(graph) has_cycles = True info('containment graph has cycles') except nx.NetworkXNoCycle: has_cycles = False if reduce: graph = nx.transitive_reduction(graph) groups = list(nx.weakly_connected_components(graph)) # noinspection PyCallingNonCallable roots = [node for node, degree in graph.in_degree() if 0 == degree] # noinspection PyCallingNonCallable leaves = [node for node, degree in graph.out_degree() if 0 == degree] return graph, groups, representative, roots, leaves, num_atoms, has_cycles, has_equal_nonequal
def find_topological_order(directory, target=None): graph = nx.DiGraph() # First, walk the installers and find real providers for root, _, files in os.walk(directory): if INSTALLER in files: name = os.path.basename(root) graph.add_node(name, transitive=False) # Second, find all dependees and dependers for root, _, files in os.walk(directory): if INSTALLER in files: name = os.path.basename(root) dependencies, satisfies = read_dependencies(os.path.join(root, INSTALLER)) for dependence in dependencies: # If by now the dependence does not have a node it does not have a real # provider, so we assume it is transitive, i.d. provided by something # with different name if not graph.has_node(dependence): graph.add_node(dependence, transitive=True) # Set edge from dependee to its provider add_edge = functools.partial(lambda a,b: graph.add_edge(b,a), name) map(add_edge, dependencies) for sat in satisfies: # If there is something that tries to satisfy already satisfied # dependency we consider this an error if graph.has_node(sat) and len(list(graph.predecessors(sat))): print("{} tries to satisfy already existing installer {}".format(name, sat)) return False, None graph.add_node(sat, transitive=True) # Set edge from transitive provider to its real provider add_edge = functools.partial(lambda a,b: graph.add_edge(a,b), name) map(add_edge, satisfies) # print graph.edges() # sys.exit(0) # Not all dependencies are provided by installers of the same name. By # collapsing the graph on these 'satisfying' dependencies we point a dependee # to a right installer. for node, transitive in graph.nodes(data='transitive'): if not transitive: continue dependees = list(graph.successors(node)) providers = list(graph.predecessors(node)) assert len(providers) == 1, 'Must be exactly one provider' # Remove transitive node with all its edges graph.remove_node(node) # Reconnect the graph add_edge = functools.partial(graph.add_edge, providers[0]) map(add_edge, dependees) if not nx.is_directed_acyclic_graph(graph): print("Found dependency cycle: {}".format(nx.find_cycle(graph))) return False, None if target: closure = set([target]) while True: new = closure | set(sum(map(list, map(graph.predecessors, closure)), [])) if closure == new: break closure = new return True, list(nx.topological_sort(graph.subgraph(closure))) return True, list(nx.topological_sort(graph))
def build_graph(self): """ - 迭代添加句子,构建有向连通词图,词语添加顺序: 1. 没有候选结点或者具有明确的候选结点或者在一个句子中出现多次的非停用词 2. 具有多个候选结点的非停用词 3. 停用词 4. 标点 对于2、3、4,如果具有多个候选结点,则选择上下文和词图中的邻接结点覆盖度最大的结点。 - 为词图添加边 词图中的每个结点是一个元组('word/POS', id),同时附加一个info信息,info为一个列表, 其中存储每个包含该词的句子sentence_id和在句子中的位置position_in_sentence """ # 逐个添加句子 for i in range(self.length): # 计算句子的长度(包含的词数) sentence_len = len(self.sentence[i]) # 标记,用0初始化 mapping = [0] * sentence_len # ------------------------------------------------------------------- # 1. 没有候选结点或者具有明确的候选结点或者在一个句子中出现多次的非停用词 # ------------------------------------------------------------------- for j in range(sentence_len): token, pos, weight = self.sentence[i][j] # 如果是停用词或者标点,则跳过 if token in self.stopwords or re.search('(?u)^\W$', token): continue # 结点标识:word/-/pos node = token.lower() + self.sep + pos # 计算图中可能的候选结点的个数 k = self.ambiguous_nodes(node) # 如果图中没有结点,则新建一个结点,id为0 if k == 0: # 添加一个id为0的结点,i为句子编号,j为当前词在句子中的编号 self.graph.add_node((node, 0), info=[(i, j)], label=token.lower()) # Mark the word as mapped to k mapping[j] = (node, 0) # 只有一个匹配的结点(即id为0的结点) elif k == 1: # 获取包含当前结点的句子ID ids = [] for sid, pos_s in self.graph.node[(node, 0)]['info']: # sid为node所在句子id, pos_s为该词在句子中的位置 ids.append(sid) # 如果该结点之前没有记录,则更新该结点(更新info的值) if i not in ids: self.graph.node[(node, 0)]['info'].append((i, j)) mapping[j] = (node, 0) # 否则为当前冗余的词创建一个新的结点 else: self.graph.add_node((node, 1), info=[(i, j)], label=token.lower()) mapping[j] = (node, 1) # ------------------------------------------------------------------- # 2. 具有多个候选结点的非停用词 # ------------------------------------------------------------------- for j in range(sentence_len): token, pos, weight = self.sentence[i][j] # 如果是停用词或者标点,则跳过 if token in self.stopwords or re.search('(?u)^\W$', token): continue # 处理步骤1中未处理的词 if mapping[j] == 0: # 结点标识:word/-/pos node = token.lower() + self.sep + pos # 创建邻接结点的标识 prev_token, prev_pos, prev_weight = self.sentence[i][j-1] # 前一个词的word和pos next_token, next_pos, next_weight = self.sentence[i][j+1] # 后一个词的word和pos prev_node = prev_token.lower() + self.sep + prev_pos next_node = next_token.lower() + self.sep + next_pos # 计算图中可能的候选结点的个数 k = self.ambiguous_nodes(node) # 寻找候选结点中具有最大上下文覆盖度或最大频度的结点 ambinode_overlap = [] ambinode_frequency = [] # 依次处理每个候选结点 for l in range(k): # 获取结点的上文 l_context = self.get_directed_context(node, l, 'left') # 获取结点的下文 r_context = self.get_directed_context(node, l, 'right') # 计算对应node在相应上下文中出现的总次数 val = l_context.count(prev_node) val += r_context.count(next_node) # 保存每个候选结点的上下文覆盖度 ambinode_overlap.append(val) # 保存每个候选结点的频度 ambinode_frequency.append(len(self.graph.node[(node, l)]['info'])) # 寻找最佳候选结点(避免环路) found = False selected = 0 while not found: # 覆盖度最大的结点下标 selected = self.max_index(ambinode_overlap) # 如果覆盖度不能区分,则用最大的频度 if ambinode_overlap[selected] == 0: selected = self.max_index(ambinode_frequency) # 获取句子对应的ID ids = [] for sid, p in self.graph.node[(node, selected)]['info']: ids.append(sid) # 避免环路 if i not in ids: found = True break # Remove the candidate from the lists else: del ambinode_overlap[selected] del ambinode_frequency[selected] # Avoid endless loops if len(ambinode_overlap) == 0: break # 找到不为当前句子的最佳候选结点 if found: self.graph.node[(node, selected)]['info'].append((i, j)) mapping[j] = (node, selected) # 否则,创建一个新的结点 else: self.graph.add_node((node, k), info=[(i, j)], label=token.lower()) mapping[j] = (node, k) # ------------------------------------------------------------------- # 3. 处理停用词 # ------------------------------------------------------------------- for j in range(sentence_len): token, pos, weight = self.sentence[i][j] # 如果不是停用词,则跳过 if token not in self.stopwords: continue # 结点标识:word/-/pos node = token.lower() + self.sep + pos # 获取候选结点的数目 k = self.ambiguous_nodes(node) # If there is no node in the graph, create one with id = 0 if k == 0: # Add the node in the graph self.graph.add_node((node, 0), info=[(i, j)], label=token.lower()) # Mark the word as mapped to k mapping[j] = (node, 0) # Else find the node with overlap in context or create one else: # Create the neighboring nodes identifiers prev_token, prev_pos, prev_weight = self.sentence[i][j-1] next_token, next_pos, next_weight = self.sentence[i][j+1] prev_node = prev_token.lower() + self.sep + prev_pos next_node = next_token.lower() + self.sep + next_pos ambinode_overlap = [] # For each ambiguous node for l in range(k): # Get the immediate context words of the nodes, the # boolean indicates to consider only non stopwords l_context = self.get_directed_context(node, l, 'left', True) r_context = self.get_directed_context(node, l, 'right', True) # Compute the (directed) context sum val = l_context.count(prev_node) val += r_context.count(next_node) # Add the count of the overlapping words ambinode_overlap.append(val) # Get best overlap candidate selected = self.max_index(ambinode_overlap) # Get the sentences id of the best candidate node ids = [] for sid, pos_s in self.graph.node[(node, selected)]['info']: ids.append(sid) # Update the node in the graph if not same sentence and # there is at least one overlap in context if i not in ids and ambinode_overlap[selected] > 0: # Update the node in the graph self.graph.node[(node, selected)]['info'].append((i, j)) # Mark the word as mapped to k mapping[j] = (node, selected) # Else create a new node else: # Add the node in the graph self.graph.add_node((node, k), info=[(i, j)], label=token.lower()) # Mark the word as mapped to k mapping[j] = (node, k) # ------------------------------------------------------------------- # 4. 处理标点 # ------------------------------------------------------------------- for j in range(sentence_len): token, pos, weight = self.sentence[i][j] # 如果不是标点,则跳过 if not re.search('(?u)^\W$', token): continue # 结点标识:word/-/pos node = token.lower() + self.sep + pos # 计算相似结点的数目 k = self.ambiguous_nodes(node) # If there is no node in the graph, create one with id = 0 if k == 0: # Add the node in the graph self.graph.add_node((node, 0), info=[(i, j)], label=token.lower()) # Mark the word as mapped to k mapping[j] = (node, 0) # Else find the node with overlap in context or create one else: # Create the neighboring nodes identifiers prev_token, prev_pos, prev_weight = self.sentence[i][j-1] next_token, next_pos, next_weight = self.sentence[i][j+1] prev_node = prev_token.lower() + self.sep + prev_pos next_node = next_token.lower() + self.sep + next_pos ambinode_overlap = [] # For each ambiguous node for l in range(k): # Get the immediate context words of the nodes l_context = self.get_directed_context(node, l, 'left') r_context = self.get_directed_context(node, l, 'right') # Compute the (directed) context sum val = l_context.count(prev_node) val += r_context.count(next_node) # Add the count of the overlapping words ambinode_overlap.append(val) # Get best overlap candidate selected = self.max_index(ambinode_overlap) # Get the sentences id of the best candidate node ids = [] for sid, pos_s in self.graph.node[(node, selected)]['info']: ids.append(sid) # Update the node in the graph if not same sentence and # there is at least one overlap in context if i not in ids and ambinode_overlap[selected] > 1: # Update the node in the graph self.graph.node[(node, selected)]['info'].append((i, j)) # Mark the word as mapped to k mapping[j] = (node, selected) # Else create a new node else: # Add the node in the graph self.graph.add_node((node, k), info=[(i, j)], label=token.lower()) # Mark the word as mapped to k mapping[j] = (node, k) # ------------------------------------------------------------------- # 5. 添加边,通过为当前结点与其所有后继结点加边来解决边的稀疏性问题,确保无环 # ------------------------------------------------------------------- for pre in range(0, len(mapping) - 1): for pos in range(pre + 1, len(mapping)): self.graph.add_edge(mapping[pre], mapping[pos]) # 判定是否有环 try: # find_cycle在无环的情况下会抛出异常 nx.find_cycle(self.graph, source=mapping[pre], orientation='original') # 没有异常,说明有环,移出刚刚添加的边 self.graph.remove_edge(mapping[pre], mapping[pos]) except: # 无环 pass # 计算每条边对应的权值 for node1, node2 in self.graph.edges_iter(): self.graph.add_edge(node1, node2, weight=self.cal_edge_weight(node1, node2))
#rosalind_pcov import networkx as nx # create de Bruijn graph G = nx.DiGraph() for l in open('rosalind_pcov.txt'): u = l.rstrip() G.add_edge(u[:-1], u[1:], label=u) result = '' for edge in nx.find_cycle(G): result += edge[0][0] print(result) open('rosalind_pcov_sub.txt', 'wt').write(result)
def is_acyclic(g: Graph) -> bool: try: cycle = find_cycle(g) except NetworkXNoCycle: return True return False