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)
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
    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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
 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
Ejemplo n.º 15
0
    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
Ejemplo n.º 17
0
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
Ejemplo n.º 18
0
 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
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
    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")
Ejemplo n.º 21
0
    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))
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
 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
Ejemplo n.º 24
0
    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))
Ejemplo n.º 25
0
    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
Ejemplo n.º 26
0
    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
Ejemplo n.º 27
0
    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}")
Ejemplo n.º 29
0
    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
Ejemplo n.º 31
0
    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
Ejemplo n.º 32
0
# 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))
Ejemplo n.º 33
0
 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)
Ejemplo n.º 34
0
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
    }
Ejemplo n.º 35
0
 def checkLegal(self, G):
     return is_directed_acyclic_graph(G)
Ejemplo n.º 36
0
              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)
Ejemplo n.º 37
0
def main():
    filename = sys.argv[1]
    g = ds.getDirectedData(filename)
    res = dag.is_directed_acyclic_graph(g)
    print(str(res).lower())
Ejemplo n.º 38
0
            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')