Exemple #1
0
def read(string):
    """
    Read a graph from a string in Dot language and return it. Nodes and edges specified in the
    input will be added to the current graph.
    
    @type  string: string
    @param string: Input string in Dot format specifying a graph.
    
    @rtype: graph
    @return: Graph
    """
    
    dotG = pydot.graph_from_dot_data(string)
    
    if (dotG.get_type() == "graph"):
        G = graph()
    elif (dotG.get_type() == "digraph"):
        G = digraph()
    elif (dotG.get_type() == "hypergraph"):
        return read_hypergraph(string)
    else:
        raise InvalidGraphType
    
    # Read nodes...
    # Note: If the nodes aren't explicitly listed, they need to be
    for each_node in dotG.get_nodes():
        G.add_node(each_node.get_name())
        for each_attr_key, each_attr_val in each_node.get_attributes().items():
            G.add_node_attribute(each_node.get_name(), (each_attr_key, each_attr_val))
    
    # Read edges...
    for each_edge in dotG.get_edges():
        # Check if the nodes have been added
        if not G.has_node(each_edge.get_source()):
            G.add_node(each_edge.get_source())
        if not G.has_node(each_edge.get_destination()):
            G.add_node(each_edge.get_destination())
        
        # See if there's a weight
        if 'weight' in each_edge.get_attributes().keys():
            _wt = each_edge.get_attributes()['weight']
        else:
            _wt = 1
        
        # See if there is a label
        if 'label' in each_edge.get_attributes().keys():
            _label = each_edge.get_attributes()['label']
        else:
            _label = ''
        
        G.add_edge((each_edge.get_source(), each_edge.get_destination()), wt = _wt, label = _label)
        
        for each_attr_key, each_attr_val in each_edge.get_attributes().items():
            if not each_attr_key in ['weight', 'label']:
                G.add_edge_attribute((each_edge.get_source(), each_edge.get_destination()), \
                                            (each_attr_key, each_attr_val))
    
    return G
Exemple #2
0
def read_graph_from_string(txt):
    """Read a graph from a string, either in dot format, or our own
    compressed format.

    Returns:
        `pygraph.digraph`: Graph object.
    """
    if not txt.startswith('{'):
        return read_dot(txt)  # standard dot format

    def conv(value):
        if isinstance(value, basestring):
            return '"' + value + '"'
        else:
            return value

    # our compacted format
    doc = literal_eval(txt)
    g = digraph()

    for attrs, values in doc.get("nodes", []):
        attrs = [(k, conv(v)) for k, v in attrs]

        for value in values:
            if isinstance(value, basestring):
                node_name = value
                attrs_ = attrs
            else:
                node_name, label = value
                attrs_ = attrs + [("label", conv(label))]

            g.add_node(node_name, attrs=attrs_)

    for attrs, values in doc.get("edges", []):
        attrs_ = [(k, conv(v)) for k, v in attrs]

        for value in values:
            if len(value) == 3:
                edge = value[:2]
                label = value[-1]
            else:
                edge = value
                label = ''

            g.add_edge(edge, label=label, attrs=attrs_)

    return g
Exemple #3
0
def read_graph_from_string(txt):
    """Read a graph from a string, either in dot format, or our own
    compressed format.

    Returns:
        `pygraph.digraph`: Graph object.
    """
    if not txt.startswith('{'):
        return read_dot(txt)  # standard dot format

    def conv(value):
        if isinstance(value, basestring):
            return '"' + value + '"'
        else:
            return value

    # our compacted format
    doc = literal_eval(txt)
    g = digraph()

    for attrs, values in doc.get("nodes", []):
        attrs = [(k, conv(v)) for k, v in attrs]

        for value in values:
            if isinstance(value, basestring):
                node_name = value
                attrs_ = attrs
            else:
                node_name, label = value
                attrs_ = attrs + [("label", conv(label))]

            g.add_node(node_name, attrs=attrs_)

    for attrs, values in doc.get("edges", []):
        attrs_ = [(k, conv(v)) for k, v in attrs]

        for value in values:
            if len(value) == 3:
                edge = value[:2]
                label = value[-1]
            else:
                edge = value
                label = ''

            g.add_edge(edge, label=label, attrs=attrs_)

    return g
Exemple #4
0
def generate(num_nodes, num_edges, directed=False, weight_range=(1, 1)):
    """
    Create a random graph.
    
    @type  num_nodes: number
    @param num_nodes: Number of nodes.
    
    @type  num_edges: number
    @param num_edges: Number of edges.
    
    @type  directed: bool
    @param directed: Whether the generated graph should be directed or not.  

    @type  weight_range: tuple
    @param weight_range: tuple of two integers as lower and upper limits on randomly generated
    weights (uniform distribution).
    """
    # Graph creation
    if directed:
        random_graph = digraph()
    else:
        random_graph = graph()

    # Nodes
    nodes = range(num_nodes)
    random_graph.add_nodes(nodes)
    
    # Build a list of all possible edges
    edges = []
    edges_append = edges.append
    for x in nodes:
        for y in nodes:
            if ((directed and x != y) or (x > y)):
                edges_append((x, y))
    
    # Randomize the list
    shuffle(edges)
    
    # Add edges to the graph
    min_wt = min(weight_range)
    max_wt = max(weight_range)
    for i in range(num_edges):
        each = edges[i]
        random_graph.add_edge((each[0], each[1]), wt = randint(min_wt, max_wt))

    return random_graph
Exemple #5
0
def read(string):
    """
    Read a graph from a XML document and return it. Nodes and edges specified in the input will
    be added to the current graph.
    
    @type  string: string
    @param string: Input string in XML format specifying a graph.
    
    @rtype: graph
    @return: Graph
    """
    dom = parseString(string)
    if dom.getElementsByTagName("graph"):
        G = graph()
    elif dom.getElementsByTagName("digraph"):
        G = digraph()
    elif dom.getElementsByTagName("hypergraph"):
        return read_hypergraph(string)
    else:
        raise InvalidGraphType

    # Read nodes...
    for each_node in dom.getElementsByTagName("node"):
        G.add_node(each_node.getAttribute('id'))
        for each_attr in each_node.getElementsByTagName("attribute"):
            G.add_node_attribute(each_node.getAttribute('id'),
                                 (each_attr.getAttribute('attr'),
                                  each_attr.getAttribute('value')))

    # Read edges...
    for each_edge in dom.getElementsByTagName("edge"):
        if (not G.has_edge(
            (each_edge.getAttribute('from'), each_edge.getAttribute('to')))):
            G.add_edge((each_edge.getAttribute('from'), each_edge.getAttribute('to')), \
                wt = float(each_edge.getAttribute('wt')), label = each_edge.getAttribute('label'))
        for each_attr in each_edge.getElementsByTagName("attribute"):
            attr_tuple = (each_attr.getAttribute('attr'),
                          each_attr.getAttribute('value'))
            if (attr_tuple not in G.edge_attributes((each_edge.getAttribute('from'), \
                each_edge.getAttribute('to')))):
                G.add_edge_attribute((each_edge.getAttribute('from'), \
                    each_edge.getAttribute('to')), attr_tuple)

    return G
Exemple #6
0
def read(string):
    """
    Read a graph from a string in Dot language and return it. Nodes and edges specified in the
    input will be added to the current graph.

    @type  string: string
    @param string: Input string in Dot format specifying a graph.

    @rtype: graph
    @return: Graph
    """

    dotG = pydot.graph_from_dot_data(string)

    # This is awful, however there seems to be a major incompatibility with pygraph
    # and current pydot. Pydot now returns a list of graphs from a dot string. Rather
    # than possibly rewrite a big chunk of this lib, we'll just use the first graph.
    # Since rez only makes single graphs anyway, this should suffice.
    #
    # https://github.com/nerdvegas/rez/issues/884
    #
    # <hack>
    if isinstance(dotG, list):
        dotG = dotG[0]
    # </endhack>

    if (dotG.get_type() == "graph"):
        G = graph()
    elif (dotG.get_type() == "digraph"):
        G = digraph()
    elif (dotG.get_type() == "hypergraph"):
        return read_hypergraph(string)
    else:
        raise InvalidGraphType

    # Read nodes...
    # Note: If the nodes aren't explicitly listed, they need to be
    for each_node in dotG.get_nodes():
        G.add_node(each_node.get_name())
        for each_attr_key, each_attr_val in each_node.get_attributes().items():
            G.add_node_attribute(each_node.get_name(),
                                 (each_attr_key, each_attr_val))

    # Read edges...
    for each_edge in dotG.get_edges():
        # Check if the nodes have been added
        if not G.has_node(each_edge.get_source()):
            G.add_node(each_edge.get_source())
        if not G.has_node(each_edge.get_destination()):
            G.add_node(each_edge.get_destination())

        # See if there's a weight
        if 'weight' in each_edge.get_attributes().keys():
            _wt = each_edge.get_attributes()['weight']
        else:
            _wt = 1

        # See if there is a label
        if 'label' in each_edge.get_attributes().keys():
            _label = each_edge.get_attributes()['label']
        else:
            _label = ''

        G.add_edge((each_edge.get_source(), each_edge.get_destination()),
                   wt=_wt,
                   label=_label)

        for each_attr_key, each_attr_val in each_edge.get_attributes().items():
            if not each_attr_key in ['weight', 'label']:
                G.add_edge_attribute((each_edge.get_source(), each_edge.get_destination()), \
                                            (each_attr_key, each_attr_val))

    return G
Exemple #7
0
def get_reverse_dependency_tree(package_name,
                                depth=None,
                                paths=None,
                                build_requires=False,
                                private_build_requires=False):
    """Find packages that depend on the given package.

    This is a reverse dependency lookup. A tree is constructed, showing what
    packages depend on the given package, with an optional depth limit. A
    resolve does not occur. Only the latest version of each package is used,
    and requirements from all variants of that package are used.

    Args:
        package_name (str): Name of the package depended on.
        depth (int): Tree depth limit, unlimited if None.
        paths (list of str): paths to search for packages, defaults to
            `config.packages_path`.
        build_requires (bool): If True, includes packages' build_requires.
        private_build_requires (bool): If True, include `package_name`'s
            private_build_requires.

    Returns:
        A 2-tuple:
        - (list of list of str): Lists of package names, where each list is a
          single depth in the tree. The first list is always [`package_name`].
        - `pygraph.digraph` object, where nodes are package names, and
          `package_name` is always the leaf node.
    """
    pkgs_list = [[package_name]]
    g = digraph()
    g.add_node(package_name)

    # build reverse lookup
    it = iter_package_families(paths)
    package_names = set(x.name for x in it)
    if package_name not in package_names:
        raise PackageFamilyNotFoundError("No such package family %r" %
                                         package_name)

    if depth == 0:
        return pkgs_list, g

    bar = ProgressBar("Searching", len(package_names))
    lookup = defaultdict(set)

    for i, package_name_ in enumerate(package_names):
        it = iter_packages(name=package_name_, paths=paths)
        packages = list(it)
        if not packages:
            continue

        pkg = max(packages, key=lambda x: x.version)
        requires = []

        for variant in pkg.iter_variants():
            pbr = (private_build_requires and pkg.name == package_name)

            requires += variant.get_requires(build_requires=build_requires,
                                             private_build_requires=pbr)

        for req in requires:
            if not req.conflict:
                lookup[req.name].add(package_name_)

        bar.next()

    bar.finish()

    # perform traversal
    n = 0
    consumed = set([package_name])
    working_set = set([package_name])

    node_color = "#F6F6F6"
    node_fontsize = 10
    node_attrs = [("fillcolor", node_color), ("style", "filled"),
                  ("fontsize", node_fontsize)]

    while working_set and (depth is None or n < depth):
        working_set_ = set()

        for child in working_set:
            parents = lookup[child] - consumed
            working_set_.update(parents)
            consumed.update(parents)

            for parent in parents:
                g.add_node(parent, attrs=node_attrs)
                g.add_edge((parent, child))

        if working_set_:
            pkgs_list.append(sorted(list(working_set_)))

        working_set = working_set_
        n += 1

    return pkgs_list, g
def get_reverse_dependency_tree(package_name, depth=None, paths=None):
    """Find packages that depend on the given package.

    This is a reverse dependency lookup. A tree is constructed, showing what
    packages depend on the given package, with an optional depth limit. A
    resolve does not occur. Only the latest version of each package is used,
    and requirements from all variants of that package are used.

    Args:
        package_name (str): Name of the package depended on.
        depth (int): Tree depth limit, unlimited if None.
        paths (list of str): paths to search for packages, defaults to
            `config.packages_path`.

    Returns:
        A 2-tuple:
        - (list of list of str): Lists of package names, where each list is a
          single depth in the tree. The first list is always [`package_name`].
        - `pygraph.digraph` object, where nodes are package names, and
          `package_name` is always the leaf node.
    """
    pkgs_list = [[package_name]]
    g = digraph()
    g.add_node(package_name)

    # build reverse lookup
    it = iter_package_families(paths)
    package_names = set(x.name for x in it)
    if package_name not in package_names:
        raise PackageFamilyNotFoundError("No such package family %r" % package_name)

    if depth == 0:
        return pkgs_list, g

    bar = ProgressBar("Searching", len(package_names))
    lookup = defaultdict(set)

    for i, package_name_ in enumerate(package_names):
        bar.next()
        it = iter_packages(name=package_name_, paths=paths)
        packages = list(it)
        if not packages:
            continue

        pkg = max(packages, key=lambda x: x.version)
        requires = set(pkg.requires or [])
        for req_list in pkg.variants or []:
            requires.update(req_list)

        for req in requires:
            if not req.conflict:
                lookup[req.name].add(package_name_)

    # perform traversal
    bar.finish()
    n = 0
    consumed = set([package_name])
    working_set = set([package_name])

    node_color = "#F6F6F6"
    node_fontsize = 10
    node_attrs = [("fillcolor", node_color), ("style", "filled"), ("fontsize", node_fontsize)]

    while working_set and (depth is None or n < depth):
        working_set_ = set()

        for child in working_set:
            parents = lookup[child] - consumed
            working_set_.update(parents)
            consumed.update(parents)

            for parent in parents:
                g.add_node(parent, attrs=node_attrs)
                g.add_edge((parent, child))

        if working_set_:
            pkgs_list.append(sorted(list(working_set_)))

        working_set = working_set_
        n += 1

    return pkgs_list, g
Exemple #9
0
def cut_tree(igraph, caps = None):
    """
    Construct a Gomory-Hu cut tree by applying the algorithm of Gusfield.

    @type igraph: graph
    @param igraph: Graph

    @type caps: dictionary
    @param caps: Dictionary specifying a maximum capacity for each edge. If not given, the weight of the edge
    will be used as its capacity. Otherwise, for each edge (a,b), caps[(a,b)] should be given.
    
    @rtype: dictionary
    @return: Gomory-Hu cut tree as a dictionary, where each edge is associated with its weight
    """

    #maximum flow needs a digraph, we get a graph
    #I think this conversion relies on implementation details outside the api and may break in the future
    graph = digraph()
    graph.add_graph(igraph)

    #handle optional argument
    if not caps:
        caps = {}
        for edge in graph.edges():
            caps[edge] = igraph.edge_weight(edge)

    #temporary flow variable
    f = {}

    #we use a numbering of the nodes for easier handling
    n = {}
    N = 0
    for node in graph.nodes():
        n[N] = node
        N = N + 1

    #predecessor function
    p = {}.fromkeys(range(N),0)
    p[0] = None

    for s in range(1,N):
        t = p[s]
        S = []
        #max flow calculation
        (flow,cut) = maximum_flow(graph,n[s],n[t],caps)
        for i in range(N):
            if cut[n[i]] == 0:
                S.append(i)
        
        value = cut_value(graph,flow,cut)

        f[s] = value

        for i in range(N):
            if i == s:
                continue
            if i in S and p[i] == t:
                p[i] = s
        if p[t] in S:
            p[s] = p[t]
            p[t] = s
            f[s] = f[t]
            f[t] = value

    #cut tree is a dictionary, where each edge is associated with its weight
    b = {}
    for i in range(1,N):
        b[(n[i],n[p[i]])] = f[i]
    return b
Exemple #10
0
def cut_tree(igraph, caps=None):
    """
    Construct a Gomory-Hu cut tree by applying the algorithm of Gusfield.

    @type igraph: graph
    @param igraph: Graph

    @type caps: dictionary
    @param caps: Dictionary specifying a maximum capacity for each edge. If not given, the weight of the edge
    will be used as its capacity. Otherwise, for each edge (a,b), caps[(a,b)] should be given.
    
    @rtype: dictionary
    @return: Gomory-Hu cut tree as a dictionary, where each edge is associated with its weight
    """

    #maximum flow needs a digraph, we get a graph
    #I think this conversion relies on implementation details outside the api and may break in the future
    graph = digraph()
    graph.add_graph(igraph)

    #handle optional argument
    if not caps:
        caps = {}
        for edge in graph.edges():
            caps[edge] = igraph.edge_weight(edge)

    #temporary flow variable
    f = {}

    #we use a numbering of the nodes for easier handling
    n = {}
    N = 0
    for node in graph.nodes():
        n[N] = node
        N = N + 1

    #predecessor function
    p = {}.fromkeys(range(N), 0)
    p[0] = None

    for s in range(1, N):
        t = p[s]
        S = []
        #max flow calculation
        (flow, cut) = maximum_flow(graph, n[s], n[t], caps)
        for i in range(N):
            if cut[n[i]] == 0:
                S.append(i)

        value = cut_value(graph, flow, cut)

        f[s] = value

        for i in range(N):
            if i == s:
                continue
            if i in S and p[i] == t:
                p[i] = s
        if p[t] in S:
            p[s] = p[t]
            p[t] = s
            f[s] = f[t]
            f[t] = value

    #cut tree is a dictionary, where each edge is associated with its weight
    b = {}
    for i in range(1, N):
        b[(n[i], n[p[i]])] = f[i]
    return b
Exemple #11
0
def read(string):
    """
    Read a graph from a string in Dot language and return it. Nodes and edges specified in the
    input will be added to the current graph.
    
    @type  string: string
    @param string: Input string in Dot format specifying a graph.
    
    @rtype: graph
    @return: Graph
    """

    dotG = pydot.graph_from_dot_data(string)

    if (dotG.get_type() == "graph"):
        G = graph()
    elif (dotG.get_type() == "digraph"):
        G = digraph()
    elif (dotG.get_type() == "hypergraph"):
        return read_hypergraph(string)
    else:
        raise InvalidGraphType

    # Read nodes...
    # Note: If the nodes aren't explicitly listed, they need to be
    for each_node in dotG.get_nodes():
        G.add_node(each_node.get_name())
        for each_attr_key, each_attr_val in each_node.get_attributes().items():
            G.add_node_attribute(each_node.get_name(),
                                 (each_attr_key, each_attr_val))

    # Read edges...
    for each_edge in dotG.get_edges():
        # Check if the nodes have been added
        if not G.has_node(each_edge.get_source()):
            G.add_node(each_edge.get_source())
        if not G.has_node(each_edge.get_destination()):
            G.add_node(each_edge.get_destination())

        # See if there's a weight
        if 'weight' in each_edge.get_attributes().keys():
            _wt = each_edge.get_attributes()['weight']
        else:
            _wt = 1

        # See if there is a label
        if 'label' in each_edge.get_attributes().keys():
            _label = each_edge.get_attributes()['label']
        else:
            _label = ''

        G.add_edge((each_edge.get_source(), each_edge.get_destination()),
                   wt=_wt,
                   label=_label)

        for each_attr_key, each_attr_val in each_edge.get_attributes().items():
            if not each_attr_key in ['weight', 'label']:
                G.add_edge_attribute((each_edge.get_source(), each_edge.get_destination()), \
                                            (each_attr_key, each_attr_val))

    return G