def get_graph(matrix, labels): G = nx.from_numpy_array(matrix.T, create_using=nx.DiGraph) g = nx.transitive_reduction(G) mapping = dict(zip(g, labels)) # ncenter = list(nx.topological_sort(g)) g = nx.relabel_nodes(g, mapping) return g
def graph_from_document(rows: Dict[str, List[Tuple[int, int]]]) -> nx.DiGraph: res = get_dense_matrix(rows) items = get_elementary_nodes(rows) df = matrix_to_dataframe(res, items) edges = edges_from_dataframe(df, items) graph = nx.DiGraph() graph.add_nodes_from(items) graph.add_edges_from(edges) create_entry_and_exit_nodes(graph, items) #remove_shortcuts(graph) graph = nx.transitive_reduction(graph) add_blanks(graph) #remove_shortcuts(graph) graph = nx.transitive_reduction(graph) return graph
def create_lattice(concept_class, *, parallel=True): child_map = adj_list(concept_class) clses = equiv_classes.find_equiv_cls(concept_class, child_map=child_map, parallel=parallel) g = nx.DiGraph() for cls1, cls2 in possible_edges(clses): if cls1 <= cls2: g.add_edge(cls1.rep, cls2.rep) if cls2 <= cls1: g.add_edge(cls2.rep, cls1.rep) return nx.transitive_reduction(g)
def getOptimizedGraph(self, headers_tuples): Gc = self.getClosedGraph() GMin = nx.DiGraph() for n, i in enumerate(headers_tuples): if n % 1000 == 999: print("Optimized Graph Header tuple {}".format(n)) i.append(self.initState) i.append(self.lastState) tmp = Gc.subgraph(i) tmp = nx.transitive_reduction(tmp) GMin = nx.compose(GMin, tmp) GMin = Gc.edge_subgraph(GMin.edges) return GMin
def check_relationships(branches): ancestors = {b: set() for b in branches} length = len(branches) * (len(branches) - 1) for b1, b2 in ub.ProgIter(it.combinations(branches, 2), length=length): ret = ub.cmd('git merge-base --is-ancestor {} {}'.format(b1, b2))['ret'] if ret == 0: ancestors[b1].add(b2) ret = ub.cmd('git merge-base --is-ancestor {} {}'.format(b2, b1))['ret'] if ret == 0: ancestors[b2].add(b1) print('<key> is an ancestor of <value>') print(ub.repr2(ancestors)) descendants = {b: set() for b in branches} for key, others in ancestors.items(): for o in others: descendants[o].add(key) print('<key> descends from <value>') print(ub.repr2(descendants)) import plottool as pt import networkx as nx G = nx.DiGraph() G.add_nodes_from(branches) for key, others in ancestors.items(): for o in others: # G.add_edge(key, o) G.add_edge(o, key) from networkx.algorithms.connectivity.edge_augmentation import collapse flag = True G2 = G while flag: flag = False for u, v in list(G2.edges()): if G2.has_edge(v, u): G2 = collapse(G2, [[u, v]]) node_relabel = ub.ddict(list) for old, new in G2.graph['mapping'].items(): node_relabel[new].append(old) G2 = nx.relabel_nodes(G2, {k: '\n'.join(v) for k, v in node_relabel.items()}) flag = True break G3 = nx.transitive_reduction(G2) pt.show_nx(G3, arrow_width=1.5, prog='dot', layoutkw=dict(prog='dot')) pt.zoom_factory() pt.pan_factory() pt.plt.show()
def dag(self): try: from networkx import DiGraph, transitive_reduction except ImportError: raise ImportError("the dag method requires networkx>=2.0") dag = DiGraph() for order, node in enumerate(self.funcs): dag.add_node(node, order=order) for sig1, sig2 in combinations(self.funcs, 2): if refines(sig1, sig2): dag.add_edge(sig1, sig2) elif refines(sig2, sig1): dag.add_edge(sig2, sig1) return transitive_reduction(dag)
def validate_graph(cls, value, values, **kwargs): """ Build the job.graph from the job.tasks, and ensure that the graph is acyclic (a directed acyclic graph). """ graph = nx.DiGraph() for task_name, task in (values.get('tasks') or {}).items(): graph.add_node(task_name) # make sure every task is added for depend_name in task.depends: graph.add_edge(depend_name, task_name) if not nx.is_directed_acyclic_graph(graph): raise ValueError( 'The tasks graph must be acyclic, but it currently includes cycles.' ) # the transitive reduction ensures the shortest version of the workflow. return nx.transitive_reduction(graph)
def buildDAGadjacencyMatrix(GEM, met_orders): # Build full graph adjacency matrix total_mets = np.unique( np.array([[met_pairs[0], met_pairs[1]] for met_pairs in met_orders]).flatten()).tolist() N_nodes = len(total_mets) A = np.zeros((N_nodes, N_nodes)) for met_pair in met_orders: i, j = total_mets.index(met_pair[0]), total_mets.index(met_pair[1]) A[i, j] = met_pair[2] # Get transitive reduction of the graph G = nx.from_numpy_matrix(A, create_using=nx.DiGraph()) G_plus = nx.transitive_reduction(G) # Get adjacency matrix of the transitive reduction A_plus = nx.to_numpy_matrix(G) return (A_plus, total_mets)
def getGraph(self): """ Construct a the transitive reduction of the graph representing flux order relations. Only after calling either of both buildFluxOrderDataFrame or findFluxOrderRelations methods. Returns ------- A networkx graph object """ if not hasattr(self, 'A'): raise ValueError("""Adjacency matrix missing! Call .buildFluxOrderDataFrame or .findFluxOrderRelations first""") collapsed = self.__collapseFullyCoupledWithEqualFlux() collapsed_Adjacency_Matrix = collapsed['A'] collapsed_GEM = collapsed['GEM'] A = collapsed_Adjacency_Matrix.values G = nx.from_numpy_matrix(A, create_using=nx.DiGraph()) G_plus = nx.transitive_reduction(G) nodeMap = {} nodeAttributes = {} nodes = list(G_plus.nodes) reactions = collapsed_GEM.reactions for i in range(len(nodes)): nodeMap[nodes[i]] = reactions[nodes[i]].id nodeAttributes[nodes[i]] = { 'name': reactions[nodes[i]].name, 'subsystem': reactions[nodes[i]].subsystem, 'macrosystem': reactions[nodes[i]].macrosystem } nx.set_node_attributes(G_plus, nodeAttributes) G_out = nx.relabel_nodes(G_plus, nodeMap, copy=False) isolated_nodes = list(nx.isolates(G_out)) G_out.remove_nodes_from(isolated_nodes) self.G = G_out return OrderGraph(G_out)
def induced_connected_subgraph(G, nodes): _nodes = set(nodes) g = nx.DiGraph() g.add_nodes_from(G) g.add_edges_from(G.edges) roots = list(filter(lambda n: g.in_degree(n)==0, g)) W = set(roots) while len(W)>0: n = W.pop() successors = list(g.successors(n)) if n in _nodes: for successor in successors: W.add(successor) else: for successor in successors: W.add(successor) for predecessor in filter(lambda p: p in _nodes, g.predecessors(n)): g.add_edge(predecessor, successor) g.remove_nodes_from(list(filter(lambda n: n not in _nodes, g))) g = nx.transitive_reduction(g) return g
def circuit_to_dag(c: qiskit.circuit.QuantumCircuit) -> nx.DiGraph: dag = nx.DiGraph() qubit_last_use = {} null_op = LabeledOp([None, []], -1) for index, instruction in enumerate(c): op = LabeledOp(instruction, index) for qubit in op.qubits: if qubit not in qubit_last_use: dag.add_edge(null_op, op) else: dag.add_edge(qubit_last_use[qubit], op) qubit_last_use[qubit] = op final_op = LabeledOp([None, []], float('inf')) for q in qubit_last_use: dag.add_edge(qubit_last_use[qubit], final_op) return nx.transitive_reduction(dag)
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
graph = nx.DiGraph() with open(filename) as f: for line in f: left, right = line.strip().split(')') if left not in graph: graph.add_node(left) if right not in graph: graph.add_node(right) graph.add_edge(left, right) n_nodes = len(graph) if debug: print(len(graph)) print('should be same as') print(len(nx.transitive_reduction(graph))) if not nx.is_directed_acyclic_graph(graph): raise ValueError('Circular connections found! This is not a DAG :(') total_ancestors = 0 for node in graph: n_ancestors = len(nx.ancestors(graph, node)) total_ancestors += n_ancestors if debug: print(f'Node {node} has {n_ancestors} ancestors') print(f'Total orbitees: {total_ancestors}')
def remove_transitive_edges(self): """Removes all transitive edges from the graph.""" self._remove_all_edges_except( set(nx.transitive_reduction(self.graph).edges)) return self
nodes = list(G.nodes) numEdges = {} for node1 in nodes: for node2 in nodes: if node1 != node2: if G.number_of_edges(node1, node2) > 0: numEdges[(node1, node2)] = G.number_of_edges(node1, node2) # print(numEdges) for node in nodes: if G.number_of_edges(node, node) > 0: for i in range(G.number_of_edges(node, node)): G.remove_edge(node, node) # print(G.edges()) G = nx.transitive_reduction(G) # for x in nodes: # for y in nodes: # if x!=y: # max = -1 # maxIndex = -1 # paths = nx.all_simple_paths(G, x, y) # for i in range(len(paths)): # if len(paths[i]) > max: # max = len(paths[i]) # maxIndex = i # for i in range(len(paths)): # if i != maxIndex: # for j in range(len(paths[i])-1): # # for k in range(k, len(paths[i])): # G.remove_edge(paths[j], paths[j+1])
def weak_unmerge(subclusters, ssi_threshold): """Removes merged clusters using directed graphs approach. Parameters ---------- subclusters : array, shape = [n_subclusters] Set of n_subclusters subsets of the data. ssi_threshold : float Minimum Simpson's similarity between two subclusters for edge drawing. Returns ------- unmerged_subclusters : array, shape = [n_unmerged_subclusters] Subset of subclusters of size n_unmerged_subclusters. """ indices = np.asarray([i for i in range(len(subclusters))]) di_graph_ = nx.DiGraph() di_graph_.add_nodes_from(indices) chains = [] while (len(indices) > 0): index = indices[0] chain = [index] indices = indices[1:] for i in range(len(indices)): if ssi(subclusters[index], subclusters[indices[i]]) >= ssi_threshold: chain.append(indices[i]) chains.append(chain) for chain in chains: for i in range(len(chain)-1): di_graph_.add_edge(chain[0], chain[i+1]) di_graph_ = nx.transitive_reduction(di_graph_) potentially_unmerged_subclusters = [] unmerged_subclusters = [] merged_subclusters = [] for i in range(len(subclusters)): if di_graph_.in_degree(i) <= 1: potentially_unmerged_subclusters.append(list(subclusters[i])) elif di_graph_.in_degree(i) > 1: merged_subclusters.append(list(subclusters[i])) else: pass for subcluster in potentially_unmerged_subclusters: for merged_subcluster in merged_subclusters: if len(subcluster) >= len(merged_subcluster): if ssi(subcluster, merged_subcluster) >= ssi_threshold: break else: continue unmerged_subclusters.append(subcluster) unmerged_subclusters = unique(unmerged_subclusters) unmerged_subclusters = np.asarray(unmerged_subclusters) return unmerged_subclusters
def prepare_agraph(): node_str = request.values.get('nodes') model = request.values.get('model', 'default') info = models.get(model, default_model) nodes, errors = info.nodes(node_str, report_errors=True) if errors: flash( 'Die folgenden zentralen Knoten wurden nicht gefunden: ' + ', '.join(errors), 'warning') context = request.values.get('context', False) abs_dates = request.values.get('abs_dates', False) extra, errors = info.nodes(request.values.get('extra', ''), report_errors=True) if errors: flash( 'Die folgenden Pfadziele wurden nicht gefunden: ' + ', '.join(errors), 'warning') induced_edges = request.values.get('induced_edges', False) ignored_edges = request.values.get('ignored_edges', False) direct_assertions = request.values.get('assertions', False) paths_wo_timeline = request.values.get('paths_wo_timeline', False) no_edge_labels = request.values.get('no_edge_labels', False) tred = request.values.get('tred', False) nohl = request.values.get('nohl', False) syn = request.values.get('syn', False) inscriptions = request.values.get('inscriptions', False) order = request.values.get('order', False) collapse = request.values.get('collapse', False) direction = request.values.get('dir', 'LR').upper() central_paths = request.values.get('central_paths', 'all').lower() if direction not in {'LR', 'RL', 'TB', 'BT'}: direction = 'LR' if nodes: g = info.subgraph(*nodes, context=context, abs_dates=abs_dates, paths=extra, keep_timeline=True, paths_between_nodes=central_paths, paths_without_timeline=paths_wo_timeline, direct_assertions=direct_assertions, include_syn_clusters=syn, include_inscription_clusters=inscriptions) if induced_edges: g = info.base.subgraph(g.nodes).copy() if not ignored_edges or tred: g = remove_edges( g, lambda u, v, attr: attr.get('ignore', False) and not attr.get( 'kind', '') == 'temp-syn') if not syn: g = remove_edges( g, lambda u, v, attr: attr.get('kind', None) == "temp-syn") if tred: g = remove_edges(g, lambda u, v, attr: attr.get('delete', False)) if tred: if nx.is_directed_acyclic_graph(g): reduction = nx.transitive_reduction(g) g = g.edge_subgraph([ (u, v, k) for u, v, k, _ in expand_edges(g, reduction.edges) ]) else: flash('Cannot produce DAG – subgraph is not acyclic!?', 'error') g = simplify_timeline(g) if collapse: g = collapse_parallel_edges(g) g.add_nodes_from(nodes) if order: g = info.order_graph(g) agraph = write_dot(g, target=None, highlight=None if nohl else nodes, edge_labels=not no_edge_labels) agraph.graph_attr['basename'] = ",".join([ str(node.filename.stem if hasattr(node, 'filename') else node) for node in nodes ]) agraph.graph_attr['bgcolor'] = 'transparent' agraph.graph_attr['rankdir'] = direction if order: agraph.graph_attr['ranksep'] = '0.2' return agraph else: raise NoNodes('No nodes in graph')
def group_substructures(mols, patterns=None, mol_instantiator=unsanitized_mol_from_smiles, pattern_instantiator=mol_from_smarts, matcher=has_query_query_match, reduce=True): try: import networkx as nx except ImportError: raise ImportError('Please install networkx') # 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 logger.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 logger.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 logger.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
else: print "PROBLEMATIC CYCLE", cycle #nx.write_graphml(subg, "subgraph_%s.graphml" % ccc) # add here widths for each node for nod in dch.nodes(): dch.node[nod]["width"] = gg_orig.node[":".join(nod.split(":")[:-1]) + "_2"]["width"] print dch.nodes(), "NODES OF DCH" is_dag = nx.dag.is_directed_acyclic_graph(dch) if is_dag: dch2 = nx.transitive_reduction(dch) toremove = [] for x, y in dch.edges(): if not dch2.has_edge(x, y): toremove.append((x, y)) transitively_removed_edges[id(dch)] = {} for x, y in toremove: transitively_removed_edges[id(dch)][(x, y)] = max(0, dch[x][y]["dist"]) dch.remove_edge(x, y) else: while True: try: cycle = list(nx.find_cycle(dch)) except nx.exception.NetworkXNoCycle: cycle = [] if cycle == []:
def agraph(nodeinfo: NodeInput = Depends(), context: bool = False, abs_dates: bool = False, induced_edges: bool = False, ignored_edges: bool = False, assertions: bool = False, extra: str = '', paths_wo_timeline: bool = False, tred: bool = False, nohl: bool = False, syn: bool = False, inscriptions: bool = False, order: bool = False, collapse: bool = False, dir: Direction = Direction.LR, central_paths: CentralPaths = CentralPaths.ALL, no_edge_labels: bool = False) -> _AGraphInfo: """ Creates the actual graph. """ # retrieve the nodes by string model = models[nodeinfo.model] nodes, unknown_nodes = model.nodes(nodeinfo.nodes, report_errors=True) extra_nodes, unknown_extra_nodes = model.nodes(extra, report_errors=True) # extract the basic subgraph g = model.subgraph(*nodes, context=context, abs_dates=abs_dates, paths=extra_nodes, paths_without_timeline=paths_wo_timeline, paths_between_nodes=central_paths.value, direct_assertions=assertions, include_syn_clusters=syn, include_inscription_clusters=inscriptions) if induced_edges: # TODO refactor into model.subgraph? g = model.base.subgraph(g.nodes).copy() # now remove ignored or conflicting edges, depending on the options if not ignored_edges or tred: g = remove_edges(g, lambda u, v, attr: attr.get('ignore', False) and not attr.get('kind', '') == 'temp-syn') if not syn: g = remove_edges(g, lambda u, v, attr: attr.get('kind', None) == 'temp-syn') if tred: g = remove_edges(g, lambda u, v, attr: attr.get('delete', False)) # now actual tred if nx.is_directed_acyclic_graph(g): reduction = nx.transitive_reduction(g) g = g.edge_subgraph([(u, v, k) for u, v, k, _ in expand_edges(g, reduction.edges)]) else: raise HTTPException(500, dict( error="not-acyclic", msg='Cannot produce transitive reduction – the subgraph is not acyclic after removing conflict edges!', dot=write_dot(g, target=None, highlight=nodes).to_string())) g = simplify_timeline(g) if collapse: g = collapse_parallel_edges(g) # make sure the central nodes are actually in the subgraph. They might theoretically have fallen out by # one of the reduction operations before, e.g., the edge subgraph required for tred g.add_nodes_from(nodes) # now we have our subgraph. All following operations are visualisation focused if order: g = model.order_graph(g) # adjusts weights & invisible edges to make graphviz layout the nodes in # a straight line according to the order of the model agraph = write_dot(g, target=None, highlight=None if nohl else nodes, edge_labels=not no_edge_labels) basename = ",".join( [str(node.filename.stem if hasattr(node, 'filename') else node) for node in nodes]) agraph.graph_attr['bgcolor'] = 'transparent' agraph.graph_attr['rankdir'] = dir.value if order: agraph.graph_attr['ranksep'] = '0.2' return _AGraphInfo(agraph, nodes, extra_nodes, unknown_nodes + unknown_extra_nodes, basename)