Пример #1
0
 def test_chordal_find_cliques(self):
     cliques = {
         frozenset([9]),
         frozenset([7, 8]),
         frozenset([1, 2, 3]),
         frozenset([2, 3, 4]),
         frozenset([3, 4, 5, 6]),
     }
     assert nx.chordal_graph_cliques(self.chordal_G) == cliques
     with pytest.raises(nx.NetworkXError, match="Input graph is not chordal"):
         nx.chordal_graph_cliques(self.non_chordal_G)
     with pytest.raises(nx.NetworkXError, match="Input graph is not chordal"):
         nx.chordal_graph_cliques(self.self_loop_G)
Пример #2
0
 def max_cliques(self):
     if len(self._arcs) == 0:
         g = self.to_nx()
         m_cliques = nx.chordal_graph_cliques(g)
         return {frozenset(c) for c in m_cliques}
     else:
         return set.union(*(cc.max_cliques() for cc in self.chain_components()))
Пример #3
0
 def test_chordal_find_cliques_path(self):
     G = nx.path_graph(10)
     cliqueset = nx.chordal_graph_cliques(G)
     for (u, v) in G.edges():
         assert_true(
             frozenset([u, v]) in cliqueset
             or frozenset([v, u]) in cliqueset)
Пример #4
0
 def test_chordal_find_cliquesCC(self):
     cliques = set([
         frozenset([1, 2, 3]),
         frozenset([2, 3, 4]),
         frozenset([3, 4, 5, 6])
     ])
     assert_equal(nx.chordal_graph_cliques(self.connected_chordal_G),
                  cliques)
Пример #5
0
 def test_chordal_find_cliques(self):
     cliques = {
         frozenset([9]),
         frozenset([7, 8]),
         frozenset([1, 2, 3]),
         frozenset([2, 3, 4]),
         frozenset([3, 4, 5, 6]),
     }
     assert nx.chordal_graph_cliques(self.chordal_G) == cliques
Пример #6
0
def cliques(graph):
    G = nx.Graph()
    for n in graph:
        G.add_node(n)
    for n in graph:
        for e in graph[n]:
            G.add_edge(n, e)

    C = list(nx.chordal_graph_cliques(G))
    for i in range(len(C)):
        C[i] = list(C[i])
    return C
Пример #7
0
def chordal_graph_treewidth(G):
    """Returns the treewidth of the chordal graph G.

    Parameters
    ----------
    G : graph
      A NetworkX graph

    Returns
    -------
    treewidth : int
        The size of the largest clique in the graph minus one.

    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
        If the input graph is an instance of one of these classes, a
        :exc:`NetworkXError` is raised.
        The algorithm can only be applied to chordal graphs. If the input
        graph is found to be non-chordal, a :exc:`NetworkXError` is raised.

    Examples
    --------
    >>> e = [
    ...     (1, 2),
    ...     (1, 3),
    ...     (2, 3),
    ...     (2, 4),
    ...     (3, 4),
    ...     (3, 5),
    ...     (3, 6),
    ...     (4, 5),
    ...     (4, 6),
    ...     (5, 6),
    ...     (7, 8),
    ... ]
    >>> G = nx.Graph(e)
    >>> G.add_node(9)
    >>> nx.chordal_graph_treewidth(G)
    3

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Tree_decomposition#Treewidth
    """
    if not is_chordal(G):
        raise nx.NetworkXError("Input graph is not chordal.")

    max_clique = -1
    for clique in nx.chordal_graph_cliques(G):
        max_clique = max(max_clique, len(clique))
    return max_clique - 1
Пример #8
0
def compute_chromatic(masses, window):
    G = nx.Graph()
    for i in range(0, len(masses)):
        G.add_node(i)
    for i in range(0, len(masses)):
        for j in range(i + 1, len(masses)):
            if abs(masses[j] - masses[i]) <= window*2.0:
                G.add_edge(i, j)
            else:
                break
    assert(nx.is_chordal(G))
    setlist = nx.chordal_graph_cliques(G)
    return max([len(x) for x in setlist])
Пример #9
0
def get_clique_tree(nodes: Iterable[int], edges: List[Tuple[int,
                                                            int]]) -> nx.Graph:
    """
    Given a set of int nodes i and edges (i,j), returns a clique tree.

    Clique tree is an object G for which:
    - G.nodes[i]['members'] contains the set of original nodes in the ith
        maximal clique
    - G[i][j]['members'] contains the set of original nodes in the seperator
        set between maximal cliques i and j

    Note: This method is currently only implemented for chordal graphs; TODO:
    add a step to triangulate non-chordal graphs.

    Parameters
    ----------
    nodes
        A list of nodes indices
    edges
        A list of tuples, where each tuple has indices for connected nodes

    Returns
    -------
    networkx.Graph
        An object G representing clique tree
    """
    # Form the original graph G1
    G1 = nx.Graph()
    G1.add_nodes_from(nodes)
    G1.add_edges_from(edges)

    # Check if graph is chordal
    # TODO: Add step to triangulate graph if not
    if not nx.is_chordal(G1):
        raise NotImplementedError("Graph triangulation not implemented.")

    # Create maximal clique graph G2
    # Each node is a maximal clique C_i
    # Let w = |C_i \cap C_j|; C_i, C_j have an edge with weight w if w > 0
    G2 = nx.Graph()
    for i, c in enumerate(nx.chordal_graph_cliques(G1)):
        G2.add_node(i, members=c)
    for i in G2.nodes:
        for j in G2.nodes:
            S = G2.nodes[i]["members"].intersection(G2.nodes[j]["members"])
            w = len(S)
            if w > 0:
                G2.add_edge(i, j, weight=w, members=S)

    # Return a minimum spanning tree of G2
    return nx.minimum_spanning_tree(G2)
Пример #10
0
    def initialize_tree(self):
        """
        Initialize the structure of a clique tree, using
        the following steps:
            - Moralize graph (i.e. marry parents)
            - Triangulate graph (i.e. make graph chordal)
            - Get max cliques (i.e. community/clique detection)
            - Max spanning tree over sepset cardinality (i.e. create tree)
        
        """
        ### MORALIZE GRAPH & MAKE IT CHORDAL ###
        chordal_G = make_chordal(self.bn) # must return a networkx object
        V = chordal_G.nodes()

        ### GET MAX CLIQUES FROM CHORDAL GRAPH ###
        C = {} # key = vertex, value = clique object
        max_cliques = reversed(list(nx.chordal_graph_cliques(chordal_G)))
        for v_idx,clique in enumerate(max_cliques):
            C[v_idx] = Clique(set(clique))

        ### MAXIMUM SPANNING TREE OVER COMPLETE GRAPH TO MAKE A TREE ###
        weighted_edge_dict = dict([(c_idx,{}) for c_idx in xrange(len(C))])
        for i in range(len(C)):
            for j in range(len(C)):
                if i!=j:
                    intersect_cardinality = len(C[i].sepset(C[j]))
                    weighted_edge_dict[i][j] = -1*intersect_cardinality
        mst_G = mst(weighted_edge_dict)
        ### SET V,E,C ###
        self.E = mst_G # dictionary
        self.V = mst_G.keys() # list
        self.C = C

        
        ### ASSIGN EACH FACTOR TO ONE CLIQUE ONLY ###
        v_a = dict([(rv, False) for rv in self.bn.nodes()])
        for clique in self.C.values():
            temp_scope = []
            for var in v_a:
                if v_a[var] == False and set(self.bn.scope(var)).issubset(clique.scope):
                    temp_scope.append(var)
                    v_a[var] = True
            clique._F = Factorization(self.bn, temp_scope)

        ### COMPUTE INITIAL POTENTIAL FOR EACH FACTOR ###
        # - i.e. multiply all of its assigned factors together
        for i, clique in self.C.items():
            if len(self.parents(i)) == 0:
                clique.is_ready = True
            clique.initialize_psi()
Пример #11
0
    def initialize_tree(self):
        """
        Initialize the structure of a clique tree, using
        the following steps:
            - Moralize graph (i.e. marry parents)
            - Triangulate graph (i.e. make graph chordal)
            - Get max cliques (i.e. community/clique detection)
            - Max spanning tree over sepset cardinality (i.e. create tree)
        
        """
        ### MORALIZE GRAPH & MAKE IT CHORDAL ###
        chordal_G = make_chordal(self.bn)  # must return a networkx object
        V = chordal_G.nodes()

        ### GET MAX CLIQUES FROM CHORDAL GRAPH ###
        C = {}  # key = vertex, value = clique object
        max_cliques = reversed(list(nx.chordal_graph_cliques(chordal_G)))
        for v_idx, clique in enumerate(max_cliques):
            C[v_idx] = Clique(set(clique))

        ### MAXIMUM SPANNING TREE OVER COMPLETE GRAPH TO MAKE A TREE ###
        weighted_edge_dict = dict([(c_idx, {}) for c_idx in xrange(len(C))])
        for i in range(len(C)):
            for j in range(len(C)):
                if i != j:
                    intersect_cardinality = len(C[i].sepset(C[j]))
                    weighted_edge_dict[i][j] = -1 * intersect_cardinality
        mst_G = mst(weighted_edge_dict)
        ### SET V,E,C ###
        self.E = mst_G  # dictionary
        self.V = mst_G.keys()  # list
        self.C = C

        ### ASSIGN EACH FACTOR TO ONE CLIQUE ONLY ###
        v_a = dict([(rv, False) for rv in self.bn.nodes()])
        for clique in self.C.values():
            temp_scope = []
            for var in v_a:
                if v_a[var] == False and set(self.bn.scope(var)).issubset(
                        clique.scope):
                    temp_scope.append(var)
                    v_a[var] = True
            clique._F = Factorization(self.bn, temp_scope)

        ### COMPUTE INITIAL POTENTIAL FOR EACH FACTOR ###
        # - i.e. multiply all of its assigned factors together
        for i, clique in self.C.items():
            if len(self.parents(i)) == 0:
                clique.is_ready = True
            clique.initialize_psi()
def build_clique_graph(G):
    clique_graph = nx.Graph()
    max_cliques = nx.chordal_graph_cliques(make_chordal(G))
    # The case where there is only 1 max_clique
    if len(max_cliques) == 1:
        clique_graph.add_node(max_cliques.pop())
        return clique_graph

    for c1, c2 in combinations(max_cliques, 2):
        intersect = c1.intersection(c2)
        if len(intersect) != 0:
            # we put a minus sign because networkx only allows for MINIMUM Spanning Trees...
            clique_graph.add_edge(c1, c2, weight=-len(intersect))
        else:
            clique_graph.add_node(c1)
            clique_graph.add_node(c2)
    return clique_graph
Пример #13
0
def chordal_graph_treewidth(G):
    """Returns the treewidth of the chordal graph G.

    Parameters
    ----------
    G : graph
      A NetworkX graph

    Returns
    -------
    treewidth : int
        The size of the largest clique in the graph minus one.

    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
        If the input graph is an instance of one of these classes, a
        :exc:`NetworkXError` is raised.
        The algorithm can only be applied to chordal graphs. If
        the input graph is found to be non-chordal, a :exc:`NetworkXError` is raised.

    Examples
    --------
    >>> import networkx as nx
    >>> e = [(1,2),(1,3),(2,3),(2,4),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6),(7,8)]
    >>> G = nx.Graph(e)
    >>> G.add_node(9)
    >>> nx.chordal_graph_treewidth(G)
    3

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Tree_decomposition#Treewidth
    """
    if not is_chordal(G):
        raise nx.NetworkXError("Input graph is not chordal.")

    max_clique = -1
    for clique in nx.chordal_graph_cliques(G):
        max_clique = max(max_clique, len(clique))
    return max_clique - 1
Пример #14
0
def alphac(g):
    d = hyperEdge(g)
    x = incidence_to_primal(g)
    if nx.is_chordal(x):
        l = [list(i) for i in nx.chordal_graph_cliques(x)]
        t = 0
        mx = []
        for i in l:
            if len(i) > t:
                t = len(i)
        if t in (0, 1):
            return True
        for i in l:
            if len(i) == t:
                mx.append(i)
        flag = [False for i in mx]
        for i in range(len(mx)):
            for j in d:
                if sorted(mx[i]) == sorted(d[j]):
                    flag[i] = True
                    continue
        return False if False in flag else True
    else:
        return False
Пример #15
0
    def _jt_from_chordal_graph(self, return_junction_tree):
        """
        Creates a Junction tree with appropriate edges from a graph
        which is known to be chordal

        Parameters
        ----------
        return_junction_tree:
            return the junction tree, if true else return tree-width
        """
        from pgmpy.base import JunctionTree

        if return_junction_tree:
            cliques = nx.chordal_graph_cliques(self)
            jt = JunctionTree()
            jtnode = 0
            for max_clique in cliques:
                jtnode += 1
                jt.add_node(jtnode)
                jt.node[jtnode]["clique_nodes"] = max_clique
            jt.add_jt_edges()
            return jt
        else:
            return nx.chordal_graph_treewidth(self)
Пример #16
0
def get_clique_tree(nodes, edges):
    """Given a set of int nodes i and edges (i,j), returns an nx.Graph object G
    which is a clique tree, where:
        - G.node[i]['members'] contains the set of original nodes in the ith
            maximal clique
        - G[i][j]['members'] contains the set of original nodes in the seperator
            set between maximal cliques i and j
    
    Note: This method is currently only implemented for chordal graphs; TODO:
    add a step to triangulate non-chordal graphs.
    """
    # Form the original graph G1
    G1 = nx.Graph()
    G1.add_nodes_from(nodes)
    G1.add_edges_from(edges)

    # Check if graph is chordal
    # TODO: Add step to triangulate graph if not
    if not nx.is_chordal(G1):
        raise NotImplementedError("Graph triangulation not implemented.")

    # Create maximal clique graph G2
    # Each node is a maximal clique C_i
    # Let w = |C_i \cap C_j|; C_i, C_j have an edge with weight w if w > 0
    G2 = nx.Graph()
    for i, c in enumerate(nx.chordal_graph_cliques(G1)):
        G2.add_node(i, members=c)
    for i in G2.nodes:
        for j in G2.nodes:
            S = G2.node[i]['members'].intersection(G2.node[j]['members'])
            w = len(S)
            if w > 0:
                G2.add_edge(i, j, weight=w, members=S)

    # Return a minimum spanning tree of G2
    return nx.minimum_spanning_tree(G2)
Пример #17
0
 def test_chordal_find_cliquesCC(self):
     cliques = set([frozenset([1,2,3]),frozenset([2,3,4]),
                    frozenset([3,4,5,6])])
     assert_equal(nx.chordal_graph_cliques(self.connected_chordal_G),cliques)
Пример #18
0
 def test_chordal_find_cliques_path(self):
     G = nx.path_graph(10)
     cliqueset = nx.chordal_graph_cliques(G)
     for (u,v) in G.edges_iter():
         assert_true(frozenset([u,v]) in cliqueset 
                     or frozenset([v,u]) in cliqueset)
Пример #19
0
################ Configuration ###################
# NESTA GRG location
nesta_folder = '/home/jk/gdrive/GridChar/NESTA_GRGv1.1_PU/'

# where to put clique merge behavior JSON files
out_folder = 'sankey/data/'

# which networks to generate data from:
cnames = grg_metrics.nesta_v11_representative()[-21:28]
################ End configuration ###############

for cname in cnames:
    data = grg_metrics.parse_grg_case_file(nesta_folder + cname + '.json')
    G = grg_metrics.grg2nx(data)

    Gchord = grg_metrics.chordal_extension(G)
    cliques = list(nx.chordal_graph_cliques(Gchord))
    M = grg_metrics.clique_merge(cliques)
    Gm = M['Gmerge']

    d = json_graph.node_link_data(Gm)

    # write json
    fname = out_folder + cname + '.json'
    f = open(fname, 'w')
    try:
        json.dump(d, f)
    finally:
        f.close()
        print('Wrote ' + fname)