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)
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()))
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)
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)
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
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
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
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])
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)
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 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
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
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
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)
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)
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)
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)
################ 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)