def test_only_critical(self): # tests only critical vertices in form of trees, paths and stars, # expected the algorithm correctly augments G and the augmenting set # cardinality correspond the simple bound on Eswaran-Tarjan. D: nx.DiGraph = nx.DiGraph() nx.add_star(D, {i for i in range(1, 5)}) nx.add_path(D, {i for i in range(5, 10)}) D.add_nodes_from({i for i in range(10, 20)}) G, A, M = D_to_bipartite(D) assert_true(is_correctly_augmented(G, A)) sources, sinks, isolated = get_sources_sinks_isolated(D) s, t, q = len(sources), len(sinks), len(isolated) L = bipartite_matching_augmentation(G, A) assert_equal(len(L), max(s, t) + q) D.clear() D = nx.balanced_tree(2, 13, nx.DiGraph()) D.remove_node(0) G, A, M = D_to_bipartite(D) sources, sinks, isolated = get_sources_sinks_isolated(D) s, t, q = len(sources), len(sinks), len(isolated) for i in range(1): L = bipartite_matching_augmentation(G, A) assert_true(is_correctly_augmented(G, A, L)) assert_equal(len(L), max(s, t) + q)
def topology(): """ Function used for create new Graph. Execute this func first. """ try: attr = param() core_nodes = attr['core_nodes'] total_ce = attr['total_ce'] total_rr = attr['total_rr'] sum_nodes = attr['sum_nodes'] ls = attr['ls'] if total_ce > 0: nodes_ce = sorted( map(lambda x: 'CE{}'.format(x), range(0, total_ce))) #Generate nodes with name 'RX', where X is serial number nodes = sorted(map(lambda x: 'R{}'.format(x), range(0, core_nodes))) # Peers for CE nodes pe_peers = random.sample(nodes, total_ce) if total_rr > 0: pe_peers = random.sample(nodes[1:], total_ce) G = nx.DiGraph(name='Network topology - Star') nx.add_star(G, nodes) gen_edge(G, nodes, total_rr, core_nodes, pe_peers, sum_nodes, total_ce, nodes_ce, ls) else: G = nx.complete_graph(core_nodes) gen_edge(G, nodes, total_rr, core_nodes, pe_peers, sum_nodes, total_ce, nodes_ce, ls) return G except AddressValueError as value_error: print('Error: {}'.format(value_error)) except ZeroDivisionError: print('Not valid core_nodes. Allowed maximum 16 nodes!')
def setUp(self): self.partitions = [] graph = nx.Graph() nx.add_star(graph, range(20)) nx.add_path(graph, range(10)) self.partitions.append( NxPartitionGraphBased( graph, representation={node: node % 6 for node in graph})) graph = nx.DiGraph() nx.add_star(graph, range(20)) nx.add_path(graph, range(10)) self.partitions.append( NxPartitionGraphBased( graph, representation={node: node % 6 for node in graph})) self.uniform_icl_ex = IntegratedCompleteLikelihoodExact( is_directed=False, hyperprior=IntegratedCompleteLikelihoodExact.UNIFORM_HYPERPRIOR) self.jeffrey_icl_ex = IntegratedCompleteLikelihoodExact( is_directed=False, hyperprior=IntegratedCompleteLikelihoodExact.JEFFREY_HYPERPRIOR)
def test_star(self): """Closeness centrality: star """ G = nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b = nx.current_flow_closeness_centrality(G) b_answer = {'a': 1.0 / 3, 'b': 0.6 / 3, 'c': 0.6 / 3, 'd': 0.6 / 3} for n in sorted(G): assert almost_equal(b[n], b_answer[n])
def test_star(self): """Betweenness centrality: star """ G = nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b = nx.current_flow_betweenness_centrality(G, normalized=True) b_answer = {'a': 1.0, 'b': 0.0, 'c': 0.0, 'd': 0.0} for n in sorted(G): assert_almost_equal(b[n], b_answer[n])
def test_star(self): """Closeness centrality: star""" G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_closeness_centrality(G) b_answer = {"a": 1.0 / 3, "b": 0.6 / 3, "c": 0.6 / 3, "d": 0.6 / 3} for n in sorted(G): assert b[n] == pytest.approx(b_answer[n], abs=1e-7)
def test_star(self): """Betweenness centrality: star """ G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_betweenness_centrality_subset(G, list(G), list(G), normalized=True) b_answer = nx.current_flow_betweenness_centrality(G, normalized=True) for n in sorted(G): assert_almost_equal(b[n], b_answer[n])
def test_star(self): """Closeness centrality: star """ G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_closeness_centrality(G) b_answer = {"a": 1.0 / 3, "b": 0.6 / 3, "c": 0.6 / 3, "d": 0.6 / 3} for n in sorted(G): assert almost_equal(b[n], b_answer[n])
def test_star(self): """Betweenness centrality: star""" G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_betweenness_centrality(G, normalized=True) b_answer = {"a": 1.0, "b": 0.0, "c": 0.0, "d": 0.0} for n in sorted(G): assert almost_equal(b[n], b_answer[n])
def test_star(self): """Closeness centrality: star """ G=nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b=nx.current_flow_closeness_centrality(G) b_answer={'a': 1.0/3, 'b': 0.6/3, 'c': 0.6/3, 'd':0.6/3} for n in sorted(G): assert_almost_equal(b[n],b_answer[n])
def test_star(self): """Betweenness centrality: star""" G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_betweenness_centrality(G, normalized=True) b_answer = {"a": 1.0, "b": 0.0, "c": 0.0, "d": 0.0} for n in sorted(G): assert b[n] == pytest.approx(b_answer[n], abs=1e-7)
def test_star(self): """Betweenness centrality: star """ G=nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b=nx.current_flow_betweenness_centrality(G,normalized=True) b_answer={'a': 1.0, 'b': 0.0, 'c': 0.0, 'd':0.0} for n in sorted(G): assert_almost_equal(b[n],b_answer[n])
def test_star(self): "Approximate current-flow betweenness centrality: star" G = nx.Graph() nx.add_star(G, ["a", "b", "c", "d"]) b = nx.current_flow_betweenness_centrality(G, normalized=True) epsilon = 0.1 ba = approximate_cfbc(G, normalized=True, epsilon=0.5 * epsilon) for n in sorted(G): np.testing.assert_allclose(b[n], ba[n], atol=epsilon)
def mindrevosod(n): graf = nx.Graph() graf.add_nodes_from([i for i in range(n)]) graf.add_edge(0, n // 2) sez1 = [i for i in range(n // 2)] sez2 = [i for i in range(n // 2, n)] nx.add_star(graf, sez1) nx.add_star(graf, sez2) return graf
def test_star(self): "Approximate current-flow betweenness centrality: star" G=nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b=nx.current_flow_betweenness_centrality(G,normalized=True) epsilon=0.1 ba = approximate_cfbc(G,normalized=True, epsilon=0.5*epsilon) for n in sorted(G): assert_allclose(b[n],ba[n],atol=epsilon)
def test_star(self): """Betweenness centrality: star """ G = nx.Graph() nx.add_star(G, ['a', 'b', 'c', 'd']) b = nx.current_flow_betweenness_centrality_subset(G, list(G), list(G), normalized=True) b_answer = nx.current_flow_betweenness_centrality(G, normalized=True) for n in sorted(G): assert almost_equal(b[n], b_answer[n])
def test_add_star(self): G = self.G.copy() nlist = [12, 13, 14, 15] nx.add_star(G, nlist) assert_edges_equal(G.edges(nlist), [(12, 13), (12, 14), (12, 15)]) G = self.G.copy() nx.add_star(G, nlist, weight=2.0) assert_edges_equal(G.edges(nlist, data=True), [(12, 13, {'weight': 2.}), (12, 14, {'weight': 2.}), (12, 15, {'weight': 2.})])
def starTopology(G, nodes, number_of_rr, logical_system): """ Function used for create Graph of type a star. """ nx.add_star(G, nodes) loopbacks = net.genNet() #get loopback address for nodes loaddress = loopbacks.pop(0) # set loopback addres for RR nx.set_node_attributes(G, {'R0': {'type':'Route-Reflector', 'loopback': loaddress}}) # set loopback addres for other nodes [*map(lambda node: nx.set_node_attributes(G, {node: {'loopback':loaddress}}),nodes[1:])] genEdge(G, nodes, logical_system) return G
def test_add_star(self): G = self.G.copy() nlist = [12, 13, 14, 15] nx.add_star(G, nlist) assert edges_equal(G.edges(nlist), [(12, 13), (12, 14), (12, 15)]) G = self.G.copy() nx.add_star(G, nlist, weight=2.0) assert edges_equal( G.edges(nlist, data=True), [ (12, 13, { "weight": 2.0 }), (12, 14, { "weight": 2.0 }), (12, 15, { "weight": 2.0 }), ], ) G = self.G.copy() nlist = [12] nx.add_star(G, nlist) assert nodes_equal(G, list(self.G) + nlist) G = self.G.copy() nlist = [] nx.add_star(G, nlist) assert nodes_equal(G.nodes, self.Gnodes) assert edges_equal(G.edges, self.G.edges)
def setUp(self): self.partitions = [] graph = nx.Graph() nx.add_star(graph, range(20)) nx.add_path(graph, range(10)) self.partitions.append(NxPartitionGraphBased(graph, representation={node: node % 6 for node in graph})) graph = nx.DiGraph() nx.add_star(graph, range(20)) nx.add_path(graph, range(10)) self.partitions.append(NxPartitionGraphBased(graph, representation={node: node % 6 for node in graph})) self.non_degree_corrected = NewmanReinertNonDegreeCorrected(is_directed=False) self.degree_corrected = NewmanReinertDegreeCorrected(is_directed=False)
def setUp(self): self.graphs = [] graph = nx.Graph() nx.add_path(graph, range(4)) self.graphs.append(graph) graph = nx.Graph() nx.add_path(graph, range(10)) self.graphs.append(graph) graph = nx.DiGraph() nx.add_star(graph, range(4)) self.graphs.append(graph) graph = nx.DiGraph() nx.add_star(graph, range(10)) self.graphs.append(graph) graph = nx.karate_club_graph() self.graphs.append(graph) self.block_sizes = [2, 4, 2, 4, 3] self.partitions = [ NxPartition(graph, representation={ node: node % self.block_sizes[i] for node in graph }) for i, graph in enumerate(self.graphs) ] self.representations = [{ node: node % self.block_sizes[i] for node in graph } for i, graph in enumerate(self.graphs)] self.is_directed = [graph.is_directed() for graph in self.graphs] self.nodes = [len(graph.nodes) for graph in self.graphs] self.edges = [len(graph.edges) for graph in self.graphs]
def example_networkx(): G = networkx.Graph() networkx.add_star(G, [0, 1, 2, 3, 4]) networkx.add_path(G, [4, 5, 6, 7, 8]) networkx.add_star(G, [8, 9, 10, 11, 12]) networkx.add_path(G, [6, 13, 14, 15]) networkx.add_star(G, [15, 16, 17, 18]) return G
def build_logo(): shutil.rmtree("docs/_static/logo", ignore_errors=True) os.makedirs("docs/_static/logo", exist_ok=True) graph = nx.Graph() nx.add_path(graph, [0, 1, 2, 3, 4, 5, 0]) nx.add_star(graph, [6, 0, 1, 2, 3, 4, 5]) style = nxv.Style( graph={ "pad": 1 / 8, "bgcolor": "#00000000", "size": "1,1", "ratio": 1, }, node=lambda u, d: { "shape": "circle", "label": None, "width": 3 / 4, "style": "filled", "fillcolor": "#009AA6" if u % 2 else "#E37222", "penwidth": 5, }, edge={"penwidth": 5}, ) path = "docs/_static/logo/logo.svg" LOGGER.info(f"Rendering {path}") with open(path, "wb") as f: f.write(nxv.render(graph, style, algorithm="neato", format="svg")) for size in [16, 32, 40, 48, 64, 128, 256]: style_with_dpi = nxv.compose([style, nxv.Style(graph={"dpi": size})]) path = f"docs/_static/logo/logo-{size}.png" LOGGER.info(f"Rendering {path}") with open(path, "wb") as f: f.write( nxv.render(graph, style_with_dpi, algorithm="neato", format="png"))
def setUp(self): if self.is_directed: self.weighted_graph = nx.DiGraph() else: self.weighted_graph = nx.Graph() nx.add_star(self.weighted_graph, range(5)) nx.add_path(self.weighted_graph, range(4, 10)) # add a selfloop self.weighted_graph.add_edge(4, 4) self.covariate_graph = self.weighted_graph.copy() for from_node in self.weighted_graph: for to_node in self.weighted_graph: if self.weighted_graph.has_edge(from_node, to_node): self.weighted_graph[from_node][to_node][ "weight"] = from_node + to_node self.covariate_graph[from_node][to_node][ "covariate"] = from_node + to_node representation = {node: node % 3 for node in self.weighted_graph} self.weighted_partition = self.comparision_class( self.weighted_graph, representation=representation, weighted_graph=True) self.covariate_partition = self.test_class( self.covariate_graph, weighted_graph=False, with_covariate=True, representation=representation) self.unweighted_partition = self.comparision_class( self.weighted_graph, representation=representation, weighted_graph=False)
def remove_edges_from(self, ebunch): for e in ebunch: u, v = e[0:2] self.remove_edge(u, v) def clear(self): super().clear() self.fh.write("Clear graph\n") G = PrintGraph() G.add_node("foo") G.add_nodes_from("bar", weight=8) G.remove_node("b") G.remove_nodes_from("ar") print("Nodes in G: ", G.nodes(data=True)) G.add_edge(0, 1, weight=10) print("Edges in G: ", G.edges(data=True)) G.remove_edge(0, 1) G.add_edges_from(zip(range(0, 3), range(1, 4)), weight=10) print("Edges in G: ", G.edges(data=True)) G.remove_edges_from(zip(range(0, 3), range(1, 4))) print("Edges in G: ", G.edges(data=True)) G = PrintGraph() nx.add_path(G, range(10)) nx.add_star(G, range(9, 13)) pos = nx.spring_layout(G, seed=225) # Seed for reproducible layout nx.draw(G, pos) plt.show()
def __init__(self): self.pandemic = nx.Graph() self.blueCities = ["San Francisco", "Chicago", "Montreal", "New York", "Atlanta", "Washington", "London", "Madrid", "Essen", "Paris", "Milan", "St. Petersburg"] self.yellowCities = ["Los Angeles", "Mexico City", "Miami", "Bogota", "Lima", "Santiago", "Buenos Aires", "Sao Paulo", "Lagos", "Kinshasa", "Johannesburg", "Khartoum"] self.blackCities = ["Algiers", "Istanbul", "Cairo", "Moscow", "Baghdad", "Riyadh", "Tehran", "Karachi", "Mumbai", "Delhi", "Chennai", "Kolkata"] self.redCities = ["Bangkok", "Jakarta", "Beijing", "Shanghai", "Hong Kong", "Ho Chi Minh City", "Seoul", "Taipei", "Manila", "Sydney", "Tokyo", "Osaka"] self.pandemic.add_nodes_from(self.blueCities, color="blue", cubes=0) self.pandemic.add_nodes_from(self.yellowCities, color="yellow", cubes=0) self.pandemic.add_nodes_from(self.blackCities, color="black", cubes=0) self.pandemic.add_nodes_from(self.redCities, color="red", cubes=0) nx.add_star(self.pandemic, ["San Francisco", "Tokyo", "Manila", "Los Angeles", "Chicago"]) nx.add_star(self.pandemic, ["Chicago", "San Francisco", "Los Angeles", "Mexico City", "Atlanta", "Montreal"]) nx.add_star(self.pandemic, ["Montreal", "Chicago", "Washington", "New York"]) nx.add_star(self.pandemic, ["New York", "Montreal", "Washington", "London", "Madrid"]) nx.add_star(self.pandemic, ["Atlanta", "Chicago", "Washington", "Miami"]) nx.add_star(self.pandemic, ["Washington", "Miami", "Atlanta", "Montreal", "New York"]) nx.add_star(self.pandemic, ["London", "New York", "Madrid", "Paris", "Essen"]) nx.add_star(self.pandemic, ["Madrid", "Washington", "London", "Paris", "Algiers", "Sao Paulo"]) nx.add_star(self.pandemic, ["Essen", "London", "Paris", "Milan", "St. Petersburg"]) nx.add_star(self.pandemic, ["Paris", "London", "Madrid", "Algiers", "Milan", "Essen"]) nx.add_star(self.pandemic, ["Milan", "Essen", "Paris", "Istanbul"]) nx.add_star(self.pandemic, ["St. Petersburg", "Essen", "Istanbul", "Moscow"]) nx.add_star(self.pandemic, ["Los Angeles", "Sydney", "San Francisco", "Chicago", "Mexico City"]) nx.add_star(self.pandemic, ["Mexico City", "Los Angeles", "Chicago", "Miami", "Bogota", "Lima"]) nx.add_star(self.pandemic, ["Miami", "Atlanta", "Washington", "Bogota", "Mexico City"]) nx.add_star(self.pandemic, ["Bogota", "Mexico City", "Miami", "Sao Paulo", "Buenos Aires", "Lima"]) nx.add_star(self.pandemic, ["Lima", "Mexico City", "Bogota", "Santiago"]) nx.add_star(self.pandemic, ["Santiago", "Lima", "Buenos Aires"]) nx.add_star(self.pandemic, ["Buenos Aires", "Santiago", "Bogota", "Sao Paulo"]) nx.add_star(self.pandemic, ["Sao Paulo", "Bogota", "Buenos Aires", "Madrid", "Lagos"]) nx.add_star(self.pandemic, ["Lagos", "Sao Paulo", "Kinshasa", "Khartoum"]) nx.add_star(self.pandemic, ["Kinshasa", "Lagos", "Johannesburg", "Khartoum"]) nx.add_star(self.pandemic, ["Johannesburg", "Kinshasa", "Khartoum"]) nx.add_star(self.pandemic, ["Khartoum", "Lagos", "Kinshasa", "Johannesburg", "Cairo"]) nx.add_star(self.pandemic, ["Algiers", "Madrid", "Paris", "Istanbul", "Cairo"]) nx.add_star(self.pandemic, ["Istanbul", "Milan", "St. Petersburg", "Moscow", "Baghdad", "Cairo", "Algiers"]) nx.add_star(self.pandemic, ["Cairo", "Algiers", "Istanbul", "Baghdad", "Riyadh"]) nx.add_star(self.pandemic, ["Moscow", "St. Petersburg", "Tehran", "Istanbul"]) nx.add_star(self.pandemic, ["Baghdad", "Istanbul", "Cairo", "Riyadh", "Karachi", "Tehran"]) nx.add_star(self.pandemic, ["Algiers", "Cairo", "Baghdad", "Karachi"]) nx.add_star(self.pandemic, ["Tehran", "Moscow", "Delhi", "Karachi", "Baghdad"]) nx.add_star(self.pandemic, ["Karachi", "Tehran", "Delhi", "Mumbai", "Riyadh", "Baghdad"]) nx.add_star(self.pandemic, ["Mumbai", "Karachi", "Delhi", "Chennai"]) nx.add_star(self.pandemic, ["Delhi", "Tehran", "Karachi", "Mumbai", "Chennai", "Kolkata"]) nx.add_star(self.pandemic, ["Chennai", "Mumbai", "Delhi", "Kolkata", "Bangkok", "Jakarta"]) nx.add_star(self.pandemic, ["Kolkata", "Delhi", "Chennai", "Bangkok", "Hong Kong"]) nx.add_star(self.pandemic, ["Bangkok", "Chennai", "Kolkata", "Hong Kong", "Ho Chi Minh City", "Jakarta"]) nx.add_star(self.pandemic, ["Jakarta", "Chennai", "Bangkok", "Ho Chi Minh City", "Sydney"]) nx.add_star(self.pandemic, ["Beijing", "Seoul", "Shanghai"]) nx.add_star(self.pandemic, ["Shanghai", "Beijing", "Seoul", "Tokyo", "Taipei", "Hong Kong"]) nx.add_star(self.pandemic, ["Hong Kong", "Shanghai", "Taipei", "Manila", "Ho Chi Minh City", "Bangkok", "Kolkata"]) nx.add_star(self.pandemic, ["Ho Chi Minh City", "Bangkok", "Hong Kong", "Manila", "Jakarta"]) nx.add_star(self.pandemic, ["Seoul", "Beijing", "Shanghai", "Tokyo"]) nx.add_star(self.pandemic, ["Taipei", "Bangkok", "Hong Kong", "Manila", "Osaka"]) nx.add_star(self.pandemic, ["Manila", "Taipei", "Hong Kong", "Ho Chi Minh City", "Sydney", "San Francisco"]) nx.add_star(self.pandemic, ["Sydney", "Jakarta", "Manila", "Los Angeles"]) nx.add_star(self.pandemic, ["Tokyo", "Seoul", "Shanghai", "Osaka", "San Francisco"]) nx.add_star(self.pandemic, ["Osaka", "Taipei", "Tokyo"]) #Freezes the board, so no more nodes or edges can be added to the graph nx.freeze(self.pandemic) self.outbreakCounter = 0
def remove_edges_from(self, ebunch): for e in ebunch: u, v = e[0:2] self.remove_edge(u, v) def clear(self): Graph.clear(self) self.fh.write("Clear graph\n") if __name__ == '__main__': G = PrintGraph() G.add_node('foo') G.add_nodes_from('bar', weight=8) G.remove_node('b') G.remove_nodes_from('ar') print("Nodes in G: ", G.nodes(data=True)) G.add_edge(0, 1, weight=10) print("Edges in G: ", G.edges(data=True)) G.remove_edge(0, 1) G.add_edges_from(zip(range(0, 3), range(1, 4)), weight=10) print("Edges in G: ", G.edges(data=True)) G.remove_edges_from(zip(range(0, 3), range(1, 4))) print("Edges in G: ", G.edges(data=True)) G = PrintGraph() nx.add_path(G, range(10)) nx.add_star(G, range(9, 13)) nx.draw(G) plt.show()
G.add_node(1) G.add_nodes_from([3, 4, 5]) # 辺の追加 (頂点も必要に応じて追加されます) G.add_edge(1, 2) G.add_edges_from([(1, 3), (2, 5), (3, 4), (4, 5)]) # 辺の削除 G.remove_edge(3, 4) G.remove_edges_from([(1, 3), (2, 5)]) # 頂点の削除 (削除された頂点に接続されている辺も削除されます) G.remove_node(5) G.remove_nodes_from([3, 4]) # 指定したパス上の頂点と辺を追加 nx.add_path(G, [1, 2, 3, 4, 5]) # 1 → 2 → 3 → 4 → 5 # 指定した閉路上の頂点と辺を追加 nx.add_cycle(G, [1, 2, 3, 4, 5]) # 1 → 2 → 3 → 4 → 5 → 1 # 放射状に頂点と辺を追加 nx.add_star(G, [1, 2, 3, 4, 5]) # 1 → 2, 1 → 3, 1 → 4, 1 → 5 import networkx as nx G = nx.DiGraph() nx.add_path(G, [3, 5, 4, 1, 0, 2, 7, 8, 9, 6]) nx.add_path(G, [3, 0, 6, 4, 2, 7, 1, 9, 8, 5]) nx.nx_agraph.view_pygraphviz(G, prog='fdp') # pygraphvizが必要
def plot(matchers,strings,matcher_names=None,ax=None): """ Plots strings and their parent groups for multiple matchers as a graph, with groups represented as nodes that connect strings Arguments: matchers -- a matcher or list of matchers to plot strings -- a string or list of strings to plot (all connected strings will also be plotted) matcher_names -- (optional) a list of strings to label matchers in the plot legend ax -- (optional) a matplotlib axis object to draw the plot on. """ if isinstance(matchers,Matcher): matchers = [matchers] if isinstance(strings,str): strings = [strings] if not matcher_names: matcher_names = [f'matcher{i}' for i in range(len(matchers))] elif not (len(matcher_names) == len(matchers)): raise ValueError('matcher_names must be the same length as matchers') varname = lambda x: f'{x=}'.split('=')[0] # First build graph representation of the parent groups G = nx.Graph() for i,matcher in enumerate(matchers): m_groups = set(matcher[strings]) for g in m_groups: group_node = f'{matcher_names[i]}: {g}' string_nodes = matcher.groups[g] G.add_nodes_from(string_nodes,type='string',color='w') if len(string_nodes) > 1: G.add_nodes_from([group_node],type='group',color=f'C{i}',label=group_node) nx.add_star(G,[group_node] + string_nodes,color=f'C{i}') # Now plot graph components in a grid components = sorted(nx.connected_components(G),key=len,reverse=True) n_grid = int(np.ceil(np.sqrt(len(components)))) grid_xy = [(x,-y) for y in range(n_grid) for x in range(n_grid)] if ax is None: fig, ax = plt.subplots() for i,component in enumerate(components): G_sub = G.subgraph(component) x0,y0 = grid_xy[i] # Position nodes if len(component) > 1: pos = nx.random_layout(G_sub) pos = nx.kamada_kawai_layout(G_sub,pos=pos,scale=0.25) pos = {n:(x0+x,y0+y) for n,(x,y) in pos.items()} else: pos = {list(component)[0]:(x0,y0)} edges = list(G_sub.edges(data=True)) edge_coord = [[pos[n0],pos[n1]] for n0,n1,d in edges] edge_colors = [mplt.colors.to_rgba(d['color']) for n0,n1,d in edges] lc = mplt.collections.LineCollection(edge_coord,color=edge_colors,zorder=0) ax.add_collection(lc) for node,d in G_sub.nodes(data=True): x,y = pos[node] if d['type'] == 'group': ax.scatter(x,y,color=mplt.colors.to_rgb(d['color']),label=d['label'],s=50,zorder=2) else: ax.scatter(x,y,color='w',s=200,zorder=1) ax.text(x,y,node,ha='center',va='center',zorder=3) ax.axis('off') legend_handles = [mplt.lines.Line2D([],[],color=mplt.colors.to_rgb(f'C{i}'),markersize=15,marker='.',label=f'{name}') for i,name in enumerate(matcher_names)] plt.legend(handles=legend_handles, bbox_to_anchor=(0.5,-0.2),loc='lower center', ncol=3,borderaxespad=0) return ax