def construct_bayesian_network(chi_square_values, category): # sorting the chi square values in descending order chi_square_values = sorted(chi_square_values.items(), key=lambda e: e[1][0], reverse=True) print chi_square_values #Loading variable_combinations variables_combinations = load_variables_combinations(category) # creating a graph G = nx.DiGraph() # G.add_edges_from([variable_pair]) while chi_square_values: G1 = nx.DiGraph() G2 = nx.DiGraph() # Extracting first element from sorted list (variable_pair and chi-Square_value) variable_pair = chi_square_values[0][0] var1, var2 = variable_pair G1.add_edges_from(G.edges()) #checking for at most 2 parents and also if the node is already present or not # if G1.in_degree([var2]) < 2 or G1.has_node(var2) == False: G1.add_edge(var1, var2) G2.add_edges_from(G.edges()) # if G2.in_degree([var1]) < 2 or G2.has_node(var1) == False: G2.add_edge(var2, var1) s_G, s_G1 = get_log_likelihood(G, G1, category, variables_combinations) if s_G1 < s_G and is_directed_acyclic_graph(G1): G = G1 print "G1" print G.edges() s_G, s_G2 = get_log_likelihood(G, G2, category, variables_combinations) if s_G2 < s_G and is_directed_acyclic_graph(G2): G = G2 print "G2" print G.edges() # Deleting the extracted edge del chi_square_values[0] # print len(G.edges()) return G
def outer_in_graph_iter( g: nx.DiGraph, c: Optional[nx.DiGraph] = None ) -> Generator[Tuple[Set[nxGraphNodeID], Set[nxGraphNodeID]], None, None]: """For a directed graph with unique node IDs with type int, iterates from outer / leafmost / least depended upon nodes to inner nodes yielding sets of node IDs. Optionally, takes a precomputed condensed DAG of g. Properties: * yields each node ID once * successive node ID sets only depend on/point to previously visited nodes or other nodes within their set """ if len(g.nodes) == 0: raise StopIteration("graph has no nodes") # > C – The condensation graph C of G. The node labels are integers # > corresponding to the index of the component in the list of strongly # > connected components of G. C has a graph attribute named ‘mapping’ with # > a dictionary mapping the original nodes to the nodes in C to which they # > belong. Each node in C also has a node attribute ‘members’ with the set # > of original nodes in G that form the SCC that the node in C represents. # # https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.components.condensation.html#networkx.algorithms.components.condensation if not c: c = condensation(g) assert is_directed_acyclic_graph(c) for scc_ids in outer_in_dag_iter(c): descendant_scc_ids: Set[int] = set() descendant_scc_ids.update( *[descendants(c, scc_id) for scc_id in scc_ids]) yield scc_ids_to_graph_node_ids(c, scc_ids), scc_ids_to_graph_node_ids( c, descendant_scc_ids)
def outer_in_dag_iter( g: nx.DiGraph) -> Generator[Set[nxGraphNodeID], None, None]: """ For a DAG with unique node IDs with type int, iterates from outer / leafmost / least depended upon nodes to inner nodes yielding sets of node IDs. Yields each node ID once and visits them such that successive node ID sets only depend on/point to previously visited nodes. """ if len(g.nodes) == 0: raise StopIteration("graph has no nodes") if len(g.nodes) > 1 and not is_directed_acyclic_graph(g): raise Exception("graph has more than one node and is not a DAG") visited: Set[nxGraphNodeID] = set() leaf_nodes: Set[nxGraphNodeID] = set( [node for node in g.nodes() if g.out_degree(node) == 0]) yield leaf_nodes visited.update(leaf_nodes) while True: points_to_visited = set(src for (src, _) in g.in_edges(visited)) only_points_to_visited = set(node for node in points_to_visited if all( dst in visited for (_, dst) in g.out_edges(node))) new_only_points_to_visited = only_points_to_visited - visited if not bool(new_only_points_to_visited): # visited nothing new assert len(visited) == len(g.nodes) break yield new_only_points_to_visited visited.update(only_points_to_visited)
def connect(self, srcpath, destpath): """Add an edge to our Component graph from *srccompname* to *destcompname*. """ graph = self._graph srccompname, srcvarname, destcompname, destvarname = \ _cvt_names_to_graph(srcpath, destpath) if srccompname == '@xin' and destcompname != '@bin': # this is an auto-passthrough input so we need 2 links if '@bin' not in graph['@xin']: link = _Link('@xin', '@bin') graph.add_edge('@xin', '@bin', link=link) else: link = graph['@xin']['@bin']['link'] link.connect(srcvarname, '.'.join([destcompname, destvarname])) if destcompname not in graph['@bin']: link = _Link('@bin', destcompname) graph.add_edge('@bin', destcompname, link=link) else: link = graph['@bin'][destcompname]['link'] link.connect('.'.join([destcompname, destvarname]), destvarname) elif destcompname == '@xout' and srccompname != '@bout': # this is an auto-passthrough output so we need 2 links if '@xout' not in graph['@bout']: link = _Link('@bout', '@xout') graph.add_edge('@bout', '@xout', link=link) else: link = graph['@bout']['@xout']['link'] link.connect('.'.join([srccompname, srcvarname]), destvarname) if srccompname not in graph or '@bout' not in graph[srccompname]: link = _Link(srccompname, '@bout') graph.add_edge(srccompname, '@bout', link=link) else: link = graph[srccompname]['@bout']['link'] link.connect(srcvarname, '.'.join([srccompname, srcvarname])) else: try: link = graph[srccompname][destcompname]['link'] except KeyError: link = _Link(srccompname, destcompname) graph.add_edge(srccompname, destcompname, link=link) if is_directed_acyclic_graph(graph): link.connect(srcvarname, destvarname) else: # cycle found # do a little extra work here to give more info to the user # in the error message strongly_connected = strongly_connected_components(graph) if len(link) == 0: graph.remove_edge(srccompname, destcompname) for strcon in strongly_connected: if len(strcon) > 1: raise RuntimeError( 'circular dependency (%s) would be created by connecting %s to %s' % (str(strcon), '.'.join([srccompname, srcvarname]), '.'.join([destcompname, destvarname]))) self._allsrcs[destpath] = srcpath
def get_cycle_vars(graph, varmeta): # examine the graph to see if we have any cycles that we need to # deal with cycle_vars = [] # make a copy of the graph since we don't want to modify it g = graph.subgraph(graph.nodes_iter()) sizes = [] while not is_directed_acyclic_graph(g): if not sizes: # get total data sizes for subsystem connections for u,v,data in g.edges_iter(data=True): sz = 0 for node in data['varconns']: sz += varmeta[node].get('size', 0) data['conn_size'] = sz sizes.append((sz, (u,v))) sizes = sorted(sizes) strong = list(strongly_connected_components(g))[0] if len(strong) == 1: break # find the connection with the smallest data xfer for sz, (src, dest) in sizes: if src in strong and dest in strong: cycle_vars.extend(g[src][dest]['varconns']) g.remove_edge(src, dest) sizes.remove((sz, (src, dest))) break return cycle_vars
def build_dag(fname: str): """ build DAG with Networkx Parameters ---------- fname : file containing dependencies query parents req3.sql req1.sql,req2.sql Returns ------- G : directed graph """ df = pd.read_csv(fname, sep=' ', names=["node", "parents"], header='infer') # build DAG G = nx.DiGraph() for idx, row in df.iterrows(): node = row["node"] for parent in row["parents"].split(','): G.add_edge(parent, node) # reduce graph G = transitive_reduction(G) assert is_directed_acyclic_graph(G), "check it is a DAG" return G
def parse_graph(from_blocks: List[Namespace], block: Namespace) -> Dict[str, List[str]]: """Parses a graph of a block. Args: from_blocks: The input blocks. block: The block to parse its graph. Returns: Dictionary in topological order mapping node IDs to its respective input nodes IDs. Raises: ValueError: If there are problems parsing the graph. ValueError: If the graph is not directed and acyclic. ValueError: If topological sort does not include all nodes. """ if isinstance(block, dict): block = dict_to_namespace(block) if any(isinstance(x, dict) for x in from_blocks): from_blocks = [dict_to_namespace(x) for x in from_blocks] ## Get graph list ## if hasattr(block, '_class') and block._class == 'Sequential': graph_list = [ from_blocks[0]._id + ' -> ' + ' -> '.join([b._id for b in block.blocks]) ] else: graph_list = block.graph if hasattr(block, 'input') and isinstance(block.input, str): graph_list = [from_blocks[0]._id + ' -> ' + block.input ] + graph_list ## Parse graph ## try: graph = digraph_from_graph_list(graph_list) except Exception as ex: raise ValueError( f'Problems parsing graph for block[id={block._id}]: {ex}') from ex if not is_directed_acyclic_graph(graph): raise ValueError( f'Expected graph to be directed and acyclic for block[id={block._id}], graph={graph_list}.' ) ## Create topologically ordered dict mapping all nodes to its inputs ## topological_predecessors = OrderedDict() for node in topological_sort(graph): predecessors = [n for n in graph.predecessors(node)] if len(predecessors) > 0: topological_predecessors[node] = predecessors nodes_blocks = {b._id for b in block.blocks} nodes_topological = {k for k in topological_predecessors.keys()} missing = nodes_blocks - nodes_topological if len(missing) > 0: raise ValueError( f'Graph in block[id={block._id}] does not reference all of its blocks: missing={missing}.' ) return topological_predecessors
def collect(self) -> None: """collect() is run every loop, collecting Plugin resources. Every time collect() is run it creates a new working Graph. It then creates instances of each Plugin and starts their thread which in turn runs the Plugin's collect() method. Once all Plugins have finished collecting cloud resources, it retrieves the Plugin's Graphs and appends them to its own working Graph. At the end the live Graph is swapped with the working Graph. """ gc = GraphContainer( cache_graph=False ) # Create a new graph container to hold the Graph() which we'll swap out at the end dispatch_event( Event(EventType.COLLECT_BEGIN, gc.graph) ) # Let interested parties know that we're about to start our collect run plugins = [Plugin() for Plugin in self.plugins ] # Create instances of each Plugin() start_time = time.time() # First we run each Collector Plugin # Each Plugin is a threading.Thread so we call start() on it for plugin in plugins: plugin.start( ) # Run the collect() method on each plugin which in turn generates a Graph() # Now we wait for each Plugin to complete its work or time out # Because we always swap out the completed graph at the end of our collect run # it doesn't matter in which order we wait for (join) Plugins. I.e. there's no speed # advantage in checking for already completed Plugins and collecting slow ones last. for plugin in plugins: timeout = start_time + ArgumentParser.args.timeout - time.time() if timeout < 1: timeout = 1 log.info( f'Waiting for collector thread of plugin {plugin.cloud} to finish' ) plugin.join(timeout) if not plugin.is_alive(): # The plugin has finished its work if not is_directed_acyclic_graph(plugin.graph): log.error( f'Graph of plugin {plugin.cloud} is not acyclic - ignoring plugin results' ) continue log.info( f'Merging graph of plugin {plugin.cloud} with global graph' ) gc.add(plugin.graph) gc.graph.add_edge( gc.GRAPH_ROOT, plugin.root ) # Connect the root of our graph with the plugin's else: log.error( f'Plugin {plugin.cloud} timed out - discarding Plugin graph' ) sanitize(gc.graph, gc.GRAPH_ROOT) dispatch_event(Event(EventType.GENERATE_METRICS, gc.graph), blocking=True) dispatch_event(Event(EventType.COLLECT_FINISH, gc.graph), blocking=True) self.gc.graph = gc.graph # Swap the live graph with the newly created one from our current run
def construct_bayesian_network(chi_square_values, category): # sorting the chi square values in descending order chi_square_values = sorted(chi_square_values.items(), key=lambda e:e[1][0], reverse=True) print chi_square_values #Loading variable_combinations variables_combinations = load_variables_combinations(category) # creating a graph G = nx.DiGraph() # G.add_edges_from([variable_pair]) while chi_square_values: G1 = nx.DiGraph() G2 = nx.DiGraph() # Extracting first element from sorted list (variable_pair and chi-Square_value) variable_pair = chi_square_values[0][0] var1, var2 = variable_pair G1.add_edges_from(G.edges()) #checking for at most 2 parents and also if the node is already present or not # if G1.in_degree([var2]) < 2 or G1.has_node(var2) == False: G1.add_edge(var1, var2) G2.add_edges_from(G.edges()) # if G2.in_degree([var1]) < 2 or G2.has_node(var1) == False: G2.add_edge(var2, var1) s_G, s_G1 = get_log_likelihood(G, G1, category, variables_combinations) if s_G1 < s_G and is_directed_acyclic_graph(G1): G = G1 print "G1" print G.edges() s_G, s_G2 = get_log_likelihood(G, G2, category, variables_combinations) if s_G2 < s_G and is_directed_acyclic_graph(G2): G = G2 print "G2" print G.edges() # Deleting the extracted edge del chi_square_values[0] # print len(G.edges()) return G
def add_edge(i, j, g): """ Adds an edge i --> j to the graph, g. The edge is only added if this addition does NOT cause the graph to have cycles. """ g.add_edges_from([(i, j, {})]) if is_directed_acyclic_graph(g) is False: g.remove_edge(i, j)
def add_dependency(self, obj, depending_on): ng = self.g.copy() ng.add_edge(obj, depending_on) # check if adding these dependencies would add a cyclic dependency if not is_directed_acyclic_graph(ng): raise ValueError('Adding a dependency of {} on {} introduces a ' 'dependency cycle!.'.format(obj, depending_on)) self.g = ng
def check_config(self): """Check for cyclc graph.""" graph = self._get_collapsed_graph() if not is_directed_acyclic_graph(graph): # do a little extra work here to give more info to the user # in the error message strcon = strongly_connected_components(graph) self.scope.raise_exception( 'circular dependency found between' ' the following: %s' % str(strcon[0]), RuntimeError)
def check_config(self): """Check for cyclc graph.""" graph = self._get_collapsed_graph() if not is_directed_acyclic_graph(graph): # do a little extra work here to give more info to the user # in the error message strcon = strongly_connected_components(graph) self.scope.raise_exception('circular dependency found between' ' the following: %s' % str(strcon[0]), RuntimeError)
def check_deadlock_freeness(noc_rg): """ Checks if routing graph is a directed acyclic graph which would result in a deadlock-free routing algorithm :param noc_rg: NoC Routing Graph :return: True if noc_rg is deadlock free else False! """ if is_directed_acyclic_graph(noc_rg): return True else: #print(find_cycle(noc_rg, orientation='original')) return False
def add_obj(self, obj, depends_on=[]): self.g.add_node(obj) ng = self.g.copy() ng.add_edges_from((obj, d) for d in depends_on) # check if adding these dependencies would add a cyclic dependency if not is_directed_acyclic_graph(ng): raise ValueError('Adding {} with dependencies {} introduces a ' 'dependency cycle!.'.format(obj, depends_on)) self.g = ng
def from_cytoscape(cls, cytoscape_path, graph_dir): """ Loads network from cytoscape but other term data from graph_dir """ attrs = dict(name='name', ident='id') with open(cytoscape_path, "r") as f: data = json.load(f) term_graph = cls(graph_dir) name = attrs["name"] ident = attrs["ident"] graph = nx.DiGraph() #if not data.get('directed'): # raise ValueError("Cytoscape graph must be directed!") # add nodes id_to_name = {} for d in data["elements"]["nodes"]: node_name = d["data"]["value"] node_id = d["data"]["id"] graph.add_node(node_name) id_to_name[node_id] = node_name # add edges for d in data["elements"]["edges"]: source = id_to_name[d["data"].pop("source")] target = id_to_name[d["data"].pop("target")] graph.add_edge(source, target) if not is_directed_acyclic_graph(graph): cycle = find_cycle(graph) raise ValueError(f"Found cycle: {cycle}") name_to_term = {} for name in graph.nodes(): if name in term_graph.name_to_term: term = term_graph.name_to_term[name].copy() else: term = { "match_res": [], "match_fns": [], "children": [], "name": name } term["children"] = list(graph.successors(name)) name_to_term[name] = term term_graph.name_to_term = name_to_term term_graph.dag = graph return term_graph
def create_tree(inp): tree = DiGraph() for line in inp.strip().split('\n'): lhs, rhs = line.strip().split(' => ') rhs_qty, rhs_mol = rhs.strip().split() for op in lhs.strip().split(', '): qty, mol = op.strip().split() tree.add_edge(rhs_mol, mol, output_qty=int(rhs_qty), input_qty=int(qty)) assert is_directed_acyclic_graph(tree) return tree
def add_edge(self, parent_id, child_id, metadata={}): """ Adds an edge. :param parent_id: Parent node ID. :param child_id: Child node ID. :param metadata: Metadata (JSON-like). :return: DAG. """ self.g.add_edges_from([(parent_id, child_id, metadata)]) if is_directed_acyclic_graph(self.g) is False: self.g.remove_edge(parent_id, child_id) raise ValueError('adding link from parent {} to child {} will create a cycle'.format(parent_id, child_id)) return self
def __add_edge__(i, j, g): """ Adds an edge i --> j to the graph, g. The edge is only added if this addition does NOT cause the graph to have cycles. :param i: Index of a node. :param j: Index of a node. :param g: Graph. :return: None """ g.add_edges_from([(i, j, {})]) if is_directed_acyclic_graph(g) is False: g.remove_edge(i, j)
def link(self, u, v): if not self._graph.has_node(u): raise ValueError('Item %s not found to link from' % (u)) if not self._graph.has_node(v): raise ValueError('Item %s not found to link to' % (v)) self._graph.add_edge(u, v) # Ensure that there is a valid topological ordering. if not dag.is_directed_acyclic_graph(self._graph): self._graph.remove_edge(u, v) raise exc.DependencyFailure("No path through the items in the" " graph produces an ordering that" " will allow for correct dependency" " resolution")
def downhill_path(self, u, v): ''' Returns True if a downhill path from u to v exists, False otherwise. Equivalently, it evaluates the truth value of the statement "u is reachable from v" ''' if self.h(u) <= self.h(v): return False else: if not dag.is_directed_acyclic_graph(self.directed): raise TypeError('NetworkLandscape.directed must be an acyclic\ directed graph') else: return (u in dag.ancestors(self.directed, v))
def add_functions(self, funcs: Dict[str, Callable]): """ Add nodes to graph as inferred from functions Can be called multiple times. Chainable. Plan is generated and graph finalized using plan(). """ if self._is_planned: raise ValueError('Computation graph has already been planned. ' 'No further functions can be added.') for _, f in funcs.items(): self._add_function_nodes(f) if not dag.is_directed_acyclic_graph(self._graph): raise ValueError('Functions do not form a proper DAG!') return self
def is_dag_per_edge_type(self) -> bool: """ Checks if the graph is acyclic with respect to each edge type. This means it is valid if there are cycles in the graph but not for the same edge type. :return: True if the graph is acyclic for all edge types, otherwise False. """ log.debug("Ensuring graph is directed and acyclic per edge type") edges_per_type = defaultdict(list) for edge in self.edges(keys=True): if len(edge) == 3: key: EdgeKey = edge[2] edges_per_type[key.edge_type].append(edge) for edges in edges_per_type.values(): typed_graph = self.edge_subgraph(edges) if not is_directed_acyclic_graph(typed_graph): return False return True
def breakFlops(self): "Traverse the entire graph, break at flop boundaries" mod = self.__nl.mods[self.__nl.topMod] yaml = self.__nl.yaml for node in self.__cells: submod = self.node2module(node) if "clocks" in yaml[submod]: # make output port Q a circuit OUTPUT # the rationale for this (as opposed to D port) is that # some flops have things like Q=D&CIN port = yaml[submod]["outputs"].keys()[0] # wire = self.edge_label((node, self.node_neighbors[node][0])) wire = self[node][self.neighbors(node)[0]]["label"] # make a copy of the original children here before modifying # the graph # be careful! otherwise children is simply a reference! children = copy.copy(self.neighbors(node)) self.connect(node, "__OUTPUTS__", wire, port) # now create extra dummy input port portIn = str(node + "." + port) self.__flopsIn[portIn] = node self.addPortIn(portIn) self.node[portIn]["flop"] = True for child in children: if self.isCell(child): wire = self[node][child]["label"] pins = self.pins((node, child)) for pin in pins[1]: self.connect(portIn, child, wire, pins[0], pin) # remove the connection between node and child self.remove_edge(node, child) # remove any dangling nodes! self.clean() # ensure no cycles (sanity check!) if not is_directed_acyclic_graph(self): raise Exception("Cycle found!: " + str(cycle))
def parse(self): """ Organize the parsing of the Workflow Definition File or the Tool if only one tool is provided thanks to the tool command. Call the "iterate_wopfile_yml_dic_and_insert_rules_in_db()" or the "load_one_toolwrapper" (depending on the use or not of tool command) method of the reader to insert in database the set of objects of the workflow. Then, the toolwrappers of the last execution are got back before calling the dag to build itself from the set of tools. The DAG is checked to actually being a Directed Acyclic Graph. If The "--dot" option is set, the dot and ps file are wrote here. :raise: WopMarsParsingException if the workflow is not a DAG. :return: the DAG """ if not OptionManager.instance()["tool"]: self.__reader.iterate_wopfile_yml_dic_and_insert_rules_in_db( OptionManager.instance()["--wopfile"]) else: self.__reader.load_one_toolwrapper( OptionManager.instance()["TOOLWRAPPER"], OptionManager.instance()["--input"], OptionManager.instance()["--output"], OptionManager.instance()["--params"]) # Get back the set of toolwrappers of the workflow before executing them. set_toolwrappers = self.get_set_toolwrappers() dag_tools = DAG(set_toolwrappers) if not is_directed_acyclic_graph(dag_tools): # totodo LucG find out the loop to specify it in the error message raise WopMarsException( "Error while parsing the configuration file: \n\tThe workflow is malformed:", "The specified Workflow cannot be represented as a DAG.") s_dot_option = OptionManager.instance()["--dot"] if s_dot_option: Logger.instance().info( "Writing the dot and ps files representing the workflow at " + str(s_dot_option)) dag_tools.write_dot(s_dot_option) Logger.instance().debug("Dot and ps file wrote.") return dag_tools
def __init__(self, graph, sample_id=None, sex=None, phenotype=None, node_type=None, sample_index=None, num_genotyped=0): '''Construct a pedigree from a Person DAG (edge goes from parent to child).''' # Validate input if not is_directed_acyclic_graph(graph): raise ValueError('Pedigree graph must be a directed acyclic graph (DAG)') for node in graph.nodes_iter(): degree = graph.in_degree(node) if degree > 2: raise ValueError('In-degree must be at most 2, but degree[%d] = %d' % (node, degree,)) # Set defaults if sample_id is None: sample_id = graph.nodes() sex = np.tile(im.constants.INDETERMINATE, (graph.number_of_nodes(), 1)) node_type = np.tile(im.constants.INDETERMINATE, (graph.number_of_nodes(), 1)) phenotype = np.tile(im.Person.Person.PHENOTYPE_MISSING, (graph.number_of_nodes(), 1)) # Set input fields self._graph = graph self._graph_undirected = graph.to_undirected() self._sample_id = sample_id self._sample_index = sample_index if sample_index is not None else (np.arange(0, len(sample_id)) if sample_id is not None else None) self._num_genotyped = num_genotyped # Set derived fields # Reverse map sample-id -> data index if ids have been recoded self._person = dict((node, im.Person.Person(node, sex[index], phenotype[index], node_type[index], self.father(node, True), self.mother(node, True))) for (index, node) in enumerate(graph.nodes_iter())) self._node_of = dict(zip(sample_id , range(0, self.n))) if sample_id is not None else None self._index_of = dict(zip(sample_index, range(0, self.n))) if sample_index is not None else None # Lazily-initialized cached properties - node ordering self._depth = None self._preorder = None self._postorder = None # Lazily-initialized cached properties self._duos = {} self._trios = {} self._families = {} self._snp_range = None
def __init__(self, graph): '''Construct a pedigree from a Person DAG (edge goes from parent to child).''' # Validate graph if (not is_directed_acyclic_graph(graph)): raise ValueError('Pedigree graph must be a directed acyclic graph (DAG)') for node in graph.nodes_iter(): degree = graph.in_degree(node) if (degree > 2): raise ValueError('In-degree must be at most 2, but degree[%d] = %d' % (node, degree,)) # Transform data to desired form: add dummy founder nodes self.graph = graph self.graph = self.__add_dummy_founders() # Lazily-initialized cached properties self._sorted_nodes = None self._founder_nodes = None self._child_nodes = None g = self.graph for person in self.child_nodes: f, m = self.father(person), self.mother(person) g.node[person]['father'] = g.node[f]['alleles'] g.node[person]['mother'] = g.node[m]['alleles'] # print person, self.father(person), self.mother(person) # print g.node[f]['alleles'] # print g.node[person]['father'] # g.node[f]['alleles'][0] = 1000 # print g.node[f]['alleles'] # print g.node[person]['father'] # Generate founder alleles (0-based). These are fixed for all simulations. k = 0 for person in self.founder_nodes: alleles = g.node[person]['alleles'] alleles[PATERNAL] = k alleles[MATERNAL] = k + 1 k += 2 self.num_founder_alleles = k
def build_graph(self): """ Calibrates the term graph: For each term: 1. Removes all nonexistent children and parents 2. Adds the term as a child for all parents 3. Adds the term as a parent for all children """ self.dag = nx.DiGraph() self.dag.add_nodes_from(self.name_to_term.keys()) for name, term in self.name_to_term.items(): for child_name in term.setdefault("children", []): if child_name in self.name_to_term: self.dag.add_edge(name, child_name) else: # remove nonexistent children logging.info(f"Removing child {child_name} from {name}.") children = term.setdefault("children", []) children.remove(child_name) if not is_directed_acyclic_graph(self.dag): cycle = find_cycle(self.dag) raise ValueError(f"Found cycle: {cycle}")
def parse(self): """ Organize the parsing of the Workflow Definition File or the Tool if only one tool is provided thanks to the tool command. Call the "read()" or the "load_one_toolwrapper" (depending on the use or not of tool command) method of the reader to insert in database the set of objects of the workflow. Then, the toolwrappers of the last execution are got back before calling the dag to build itself from the set of tools. The DAG is checked to actually being a Directed Acyclic Graph. If The "--dot" option is set, the dot and ps file are wrote here. :raise: WopMarsParsingException if the workflow is not a DAG. :return: the DAG """ if not OptionManager.instance()["tool"]: self.__reader.read(OptionManager.instance()["--wopfile"]) else: self.__reader.load_one_toolwrapper(OptionManager.instance()["TOOLWRAPPER"], OptionManager.instance()["--input"], OptionManager.instance()["--output"], OptionManager.instance()["--params"]) # Get back the set of toolwrappers of the workflow before executing them. set_toolwrappers = self.get_set_toolwrappers() dag_tools = DAG(set_toolwrappers) if not is_directed_acyclic_graph(dag_tools): # todo find out the loop to specify it in the error message raise WopMarsException("Error while parsing the configuration file: \n\tThe workflow is malformed:", "The specified Workflow cannot be represented as a DAG.") s_dot_option = OptionManager.instance()["--dot"] if s_dot_option: Logger.instance().info("Writing the dot and ps files representing the workflow at " + str(s_dot_option)) dag_tools.write_dot(s_dot_option) Logger.instance().debug("Dot and ps file wrote.") return dag_tools
def dependency_dag(dependent_uuids, dag=None): """Create a DAG from the dependencies Parameters ---------- dependent_uuids: dict dictionary mapping UUID keys to set of UUID values, where the key-value pairs are edges of the dependency graph dag: networkx.DiGraph partially created DAG (optional) Returns ------- networkx.DiGraph DAG to recreate the input objects """ if dag is None: dag = nx.DiGraph() for from_node, to_nodes in dependent_uuids.items(): if to_nodes: dag.add_edges_from([(from_node, to_node) for to_node in to_nodes]) if not nx_dag.is_directed_acyclic_graph(dag): # pragma: no cover raise RuntimeError("Reconstruction DAG not acyclic?!?!") return dag
def learn_structure(self, data): """ Learns the BBN structure. :param data: Data. :return: DAG. """ # gets the skeleton, which is a tree, undirected graph u = get_mwst_skeleton(data) # gets all the v-structures, if any variables = data.get_variables(by_name=False) v_structures = [] for v_structure in get_v_structures(u): name1 = variables[v_structure[0]] name2 = variables[v_structure[2]] names = [variables[v_structure[1]]] cmi, result = data.is_cond_dep(name1, name2, names) if result is True: t = (v_structure[0], v_structure[1], v_structure[2], cmi) v_structures.append(t) v_structures = sorted(v_structures, key=lambda t: t[3], reverse=True) # create the DAG, this graph will have edges oriented g = nx.DiGraph() for idx in u.nodes: g.add_node(idx, name=u.nodes[idx]['name']) # attempt to orient edges by v-structures for v_structure in v_structures: left_node = v_structure[0] mid_node = v_structure[1] right_node = v_structure[2] edge1 = (left_node, mid_node, {}) edge2 = (right_node, mid_node, {}) g.add_edges_from([edge1, edge2]) if is_directed_acyclic_graph(g) is False: g.remove_edges_from([edge1, edge2]) # attempt to orient by likelihood # FIXME: note this can create v-structures missing_edges = get_missing_edges(u, g) directed_edges = get_likely_directed_edges(missing_edges, data) for edge in directed_edges: pa_node = edge[0] ch_node = edge[1] dedge = (pa_node, ch_node, {}) g.add_edges_from([dedge]) if is_directed_acyclic_graph(g) is False: g.remove_edges_from([dedge]) # now just orient randomly, so long as the graph is a dag missing_edges = get_missing_edges(u, g) while len(missing_edges) != 0: for edge in missing_edges: pa_id = np.random.randint(0, 2) ch_id = 1 if pa_id == 0 else 0 pa_node = edge[pa_id] ch_node = edge[ch_id] dedge = (pa_node, ch_node, {}) g.add_edges_from([dedge]) if is_directed_acyclic_graph(g) is False: g.remove_edges_from([dedge]) missing_edges = get_missing_edges(u, g) return g
# rosalind_dag # cycles in a graph import networkx as nx from networkx.algorithms.dag import is_directed_acyclic_graph m = open('rosalind_dag.txt').read().split('\n\n') k = int(m[0]) result = [] for g in m[1:]: lines = g.rstrip().split('\n') n, _m = [int(i) for i in lines[0].split()] nodes = [i+1 for i in range(n)] edges = [tuple([int(i) for i in j.split()]) for j in lines[1:]] G = nx.DiGraph() G.add_nodes_from(nodes) G.add_edges_from(edges) if is_directed_acyclic_graph(G): output = '1' else: output = '-1' result.append(output) print(' '.join(result)) open('rosalind_dag_sub.txt', 'wt').write(' '.join(result))
def test_is_dag_graph_type(self, graph_type): """ Tests that the generated graph is a dag for all graph types. """ degree, d_nodes = 4, 10 sm = generate_structure(d_nodes, degree, graph_type) assert is_directed_acyclic_graph(sm)
def dag(nodenum, initial_edges, ranks_wanted): if nodenum == 0: return { 'cocos': [], 'edges': { 'present': [], 'removed': [], 'closure': [], 'closing': [], 'forbidden': [] }, 'r_to_pq': [] } if nodenum == 1: return { 'cocos': [{ 'nodes': [{ 'q': 0, 'r': 0, 'x': 0, 'y': 0, 'rank': { 'min': 0, 'max': 0 } }], 'edges': [], 'svg_size': { 'x': 0, 'y': 0 }, 'longest_path_length': 0 }], 'edges': { 'present': [], 'removed': [], 'closure': [], 'closing': [], 'forbidden': [] }, 'r_to_pq': [[0, 0]] } nodes = range(nodenum) graph = nx.DiGraph() graph.add_nodes_from(nodes) graph.add_edges_from(initial_edges) if not is_directed_acyclic_graph(graph): return 'Error: The graph is not a DAG.' # transitive reduction (remove redundant edges) graph = transitive_reduction(graph) edges = list(graph.edges) removed_edges = list(set(initial_edges).difference(set(edges))) # transitive closure closure_graph = transitive_closure(graph) closure_edges = list(closure_graph.edges) closing_edges = list(set(closure_edges).difference(set(edges))) # forbidden edges (opposite edges of those in the t. c.) forbidden_edges = [] for edge in closure_edges: forbidden_edges.append((edge[1], edge[0])) # create connected components (works only from undirected graph) graph_undir = graph.to_undirected() if nx.is_connected(graph_undir): result = connected_dag(nodes, edges, ranks_wanted) cocos = [result] else: cocos = [] nodes_by_component = nx.connected_components(graph_undir) # generator for comp_nodes in nodes_by_component: comp_edges = [] for graph_edge in edges: if graph_edge[0] in comp_nodes: comp_edges.append(graph_edge) coco = connected_dag(comp_nodes, comp_edges, ranks_wanted) cocos.append(coco) # r --> (p, q) (node ID in DAG to pair of coco ID and node ID in coco) r_to_pq = [0] * nodenum for p, coco in enumerate(cocos): for node in coco['nodes']: r_to_pq[node['r']] = [p, node['q']] return { 'cocos': cocos, 'edges': { 'present': edges, # edges of the graph 'removed': removed_edges, # edges removed in transitive reduction 'closure': closure_edges, # transitive closure (present + closing) 'closing': closing_edges, # t. c. without present edges 'forbidden': forbidden_edges # edges that would create circles }, 'r_to_pq': r_to_pq }
def checkLegal(self, G): return is_directed_acyclic_graph(G)
len(next(strongly_connected_components(G))), file=f) print('#node in largest WCC:\t', len(next(weakly_connected_components(G))), file=f) print('node connectivity (approx.):\t', approx.node_connectivity(G.to_undirected()), file=f) # exact, slow # print('node connectivity:', node_connectivity(G.to_undirected())) # print('edge connectivity:', edge_connectivity(G.to_undirected())) #print('------------DAG-------------', file = f) print('Is DAG (should be true):\t', is_directed_acyclic_graph(G), file=f) print('Longest path length:\t', dag_longest_path_length(G), file=f) #print('--------Clustering--------') # exact, slow # print('Average clustering coefficient (undirected):', average_clustering(G.to_undirected())) # approximate, fast print('Average clustering coefficient (undirected, approx.):\t', approx.average_clustering(G.to_undirected()), file=f) # reprint in the file \t \t \t \t \t print("\n\n\n\n", file=f) #---------Nodes & Edges--------' print(G.number_of_nodes(), end="\t", file=f)
def main(): filename = sys.argv[1] g = ds.getDirectedData(filename) res = dag.is_directed_acyclic_graph(g) print(str(res).lower())
G.add_edge(b, y) G.nodes[y]['type'] = 'AND' elif c['type'] == 'DFF': c, d, q = conns('C', 'D', 'Q') assert c == clk_bit G.nodes[q]['type'] = 'DFF' G.nodes[q]['input_node'] = d dffs.add(q) else: unhandled_types.add(c['type']) if unhandled_types: print('didn\'t handle cell types:', unhandled_types) write_dot_with_labels(G, 'G.dot') assert nx.is_weakly_connected(G) assert dag.is_directed_acyclic_graph(G) cc = CleartextComputer(G.copy(), dffs) ec = EncryptedComputer(G.copy(), dffs) for cycle in range(10): print('evaluating cycle', cycle) print('eval cleartext') cc.step() print('eval encrypted') t0 = time.time() ec.step() t1 = time.time() dt = (t1 - t0) print(f'evaluated {len(G)} gates in {dt:.03f} s', end='') print(f', or {(dt/len(G)*1000):.03f} ms/gate')