def __generate_motifs__(x=208): """ Return the atlas of all connected graphs of 5 nodes or less. Uses networkx graph atlas, which returns all possible graphs with up to 7 nodes, based on https://networkx.github.io/documentation/stable/auto_examples/drawing/plot_atlas.html Parameters: x (int): which motifs of the graph atlas are returned Returns: graph atlas: contains all possible graphs of specified size as shown in the graph atlas """ #uses networkx graph atlas, which returns all possible graphs with up to 6 nodes #based on https://networkx.github.io/documentation/stable/auto_examples/drawing/plot_atlas.html Atlas = graph_atlas_g()[0:x] # remove isolated nodes, only connected graphs are left U = nx.Graph() # graph for union of all graphs in atlas for G in Atlas: zerodegree = [n for n in G if G.degree(n) == 0] for n in zerodegree: G.remove_node(n) U = nx.disjoint_union(U, G) # list of graphs of all connected components C = (U.subgraph(c) for c in nx.connected_components(U)) UU = nx.Graph() # do quick isomorphic-like check, not a true isomorphism checker nlist = [] # list of nonisomorphic graphs for G in C: # check against all nonisomorphic graphs so far if not __iso__(G, nlist): nlist.append(G) UU = nx.disjoint_union(UU, G) # union the nonisomorphic graphs return UU
def atlas6(): """ Return the atlas of all connected graphs of 6 nodes or less. Attempt to check for isomorphisms and remove. """ Atlas = graph_atlas_g()[0:208] # 208 # remove isolated nodes, only connected graphs are left U = nx.Graph() # graph for union of all graphs in atlas for G in Atlas: zerodegree = [n for n in G if G.degree(n) == 0] for n in zerodegree: G.remove_node(n) U = nx.disjoint_union(U, G) # list of graphs of all connected components C = nx.connected_component_subgraphs(U) UU = nx.Graph() # do quick isomorphic-like check, not a true isomorphism checker nlist = [] # list of nonisomorphic graphs for G in C: # check against all nonisomorphic graphs so far if not iso(G, nlist): nlist.append(G) UU = nx.disjoint_union(UU, G) # union the nonisomorphic graphs return UU
def setup_class(cls): global atlas # import platform # if platform.python_implementation() == 'Jython': # raise SkipTest('graph atlas not available under Jython.') import networkx.generators.atlas as atlas cls.GAG = atlas.graph_atlas_g()
def setup_class(cls): global atlas import platform if platform.python_implementation() == 'Jython': pytest.mark.skip('graph atlas not available under Jython.') import networkx.generators.atlas as atlas cls.GAG = atlas.graph_atlas_g()
def create_examples(self, file_base, file_name): """Generate some initial starting configs by generating them via the config_generator""" ex_curr = 0 num_hosts = 1 num_vlans = 2 def get_serialno(*_args, **_kwargs): """"Return mock serial number""" self.serial += 1 return self.serial def create_config(network_graph, stack=True): """Return topo object and a simple stack config generated from network_graph""" host_links = {} host_vlans = {} dp_options = {} host_n = 0 for dp_i in network_graph.nodes(): for _ in range(num_hosts): for v_i in range(num_vlans): host_links[host_n] = [dp_i] host_vlans[host_n] = v_i host_n += 1 dp_options[dp_i] = {'hardware': 'GenericTFM'} if dp_i == 0 and stack: dp_options[dp_i]['stack'] = {'priority': 1} switch_links = list(network_graph.edges()) * 2 if stack: link_vlans = {link: None for link in switch_links} else: link_vlans = {link: list(range(num_vlans)) for link in switch_links} topo = FaucetFakeOFTopoGenerator( 'ovstype', 'portsock', 'testname', len(network_graph.nodes()), False, host_links, host_vlans, switch_links, link_vlans, start_port=1, port_order=[0, 1, 2, 3], get_serialno=get_serialno) config = topo.get_config(num_vlans, dp_options=dp_options) return config configs = [] topologies = graph_atlas_g() for graph in topologies: if not graph or not networkx.is_connected(graph): continue if len(graph.nodes()) > 4: break for stack in (True, False): configs.append(create_config((graph), stack=stack)) for config in configs: ex_fn = os.path.join(file_base, '%s_%s' % (file_name, ex_curr)) with open(ex_fn, 'w+') as ex_file: ex_file.write(config) ex_curr += 1
def test_graph_atlas(self): """Test saving and loading all the graphs in the networkx graph atlas. """ for g in graph_atlas_g(): print(g.name) gormg = self.engine.new_graph(g.name, g) for n in g.node: self.assertIn(n, gormg.node) self.assertEqual(g.node[n], gormg.node[n]) for u in g.edge: for v in g.edge[u]: self.assertIn(u, gormg.edge) self.assertIn(v, gormg.edge[u]) self.assertEqual(g.edge[u][v], gormg.edge[u][v])
def get_graphlet_dict(k): """ Generate a dict of lists of all graphlets of size up to 'k', keyed by size of graphlet. Uses networkx atlas. """ from networkx.generators.atlas import graph_atlas_g assert k > 0 atlas = graph_atlas_g()[1:] graphlet_dict = {i: [] for i in range(1, k + 1)} for graph in atlas: n = graph.number_of_nodes() if n > k: break if nx.is_connected(graph): graphlet_dict[n].append(graph) return graphlet_dict
def graphlet_list(k): """ Generate list of all graphlets of size 'k'. List is taken from graph_atlas of networkx. """ from networkx.generators.atlas import graph_atlas_g assert k > 0 atlas = graph_atlas_g()[1:] graphlet_list = [] for G in atlas: n = G.number_of_nodes() if n < k: continue if n > k: break if nx.is_connected(G): graphlet_list.append(G) return graphlet_list
def isomorphism_checker(g, graph_list=None): """ Finds the name of the graph by checking for isomorphism with the graphs in the graph_list. Notes ----- If g is a MultiGraph, a DiGraph or a MultiDiGraph, the isomorphism is run against the underlying Graph. In other words, all the edge annotations (including directions) are ignored. Parameters ---------- g : A networkx Graph. graph_list : A list of networkx.Graph objects against which to check for isomorphism. If the graphs in the list do not have names, then their index will be returned as a string Returns ------- iso_name : str, or None The name of the graph from the graph_list that is isomorphic to g. If the graph does not have a 'name' attribute, its index in the list will be returned as a string. None if no such isomorph is found in the list_of_graphs. """ if graph_list is None: graph_list = graph_atlas_g() # run isomorphism check on the Graph of g (i.e. not the DiGraph or MultiGraph). h = graph_to_plain_graph(g) isomorph = next(filter(lambda x: networkx.is_isomorphic(h, x), graph_list), None) if isomorph is None: return else: iso_name = isomorph.name if iso_name is None: iso_name = str(graph_list.index(isomorph)) return iso_name
int(dst_dpid), port=dst_port) def test_generator(param): """Return the function that will start testing the topology/topologies""" def test(self): """Setup & test topology""" self.set_up(param) return test if __name__ == '__main__': GRAPHS = {} GRAPH_ATLAS = graph_atlas_g() for graph in GRAPH_ATLAS: if (not graph or len(graph.nodes()) < 2 or not networkx.is_connected(graph)): continue GRAPHS.setdefault(graph.number_of_nodes(), []) GRAPHS[graph.number_of_nodes()].append(graph) for test_class in (ValveTopologyVLANTest, ValveTopologyTableTest): test_name = 'test_%s' % graph.name test_func = test_generator(graph) setattr(test_class, test_name, test_func) for num_dps, nl in GRAPHS.items(): chunk = 50 batch = 1 for test_class in (ValveTopologyRestartTest, ): for i in range(0, len(nl), chunk):
def atlas_graphs(self): graph_list = graph_atlas_g() return graph_list
def setUp(self): self.GAG = atlas.graph_atlas_g()
====== Write first 20 graphs from the graph atlas as graphviz dot files Gn.dot where n=0,19. """ # Author: Aric Hagberg ([email protected]) # Date: 2005-05-19 14:23:02 -0600 (Thu, 19 May 2005) # Copyright (C) 2006-2019 by # Aric Hagberg <*****@*****.**> # Dan Schult <*****@*****.**> # Pieter Swart <*****@*****.**> # All rights reserved. # BSD license. import networkx as nx from networkx.generators.atlas import graph_atlas_g atlas = graph_atlas_g()[0:20] for G in atlas: print("graph %s has %d nodes with %d edges" % (G.name, nx.number_of_nodes(G), nx.number_of_edges(G))) A = nx.nx_agraph.to_agraph(G) A.graph_attr['label'] = G.name # set default node attributes A.node_attr['color'] = 'red' A.node_attr['style'] = 'filled' A.node_attr['shape'] = 'circle' A.write(G.name + '.dot')
def setup_class(cls): global atlas import networkx.generators.atlas as atlas cls.GAG = atlas.graph_atlas_g()
def setUp(self): self.GAG=atlas.graph_atlas_g()
""" ====== Atlas2 ====== Write first 20 graphs from the graph atlas as graphviz dot files Gn.dot where n=0,19. """ import networkx as nx from networkx.generators.atlas import graph_atlas_g atlas = graph_atlas_g()[0:20] for G in atlas: print(G) A = nx.nx_agraph.to_agraph(G) A.graph_attr["label"] = G.name # set default node attributes A.node_attr["color"] = "red" A.node_attr["style"] = "filled" A.node_attr["shape"] = "circle" A.write(G.name + ".dot")
class ClassGenerator: """Generates the required classes for the integration tests""" GRAPH_ATLAS = graph_atlas_g() MAX_TESTS = 150 graphs = None def __init__(self): """Initialize the graph atlas""" self.graphs = {} for graph in self.GRAPH_ATLAS: if not graph or len( graph.nodes()) < 2 or not networkx.is_connected(graph): continue self.graphs.setdefault(graph.number_of_nodes(), []) self.graphs[graph.number_of_nodes()].append(graph) @staticmethod def setup_generator(func): """Returns the class set_up function""" def set_up(self, graphs): self.graphs = graphs self.topo, self.CONFIG = self.create_topo_config(graphs[0]) self.setup_valves(self.CONFIG) func(self) return set_up @staticmethod def test_generator(graphs): """Returns the test set_up function""" def test(self): self.set_up(graphs) return test @staticmethod def sums(length, total_sum): """Returns the permutations of `length` numbers that sum to `total_sum`""" if length == 1: yield (total_sum, ) else: for value in range(total_sum + 1): for permutation in ClassGenerator.sums(length - 1, total_sum - value): yield (value, ) + permutation def generate_atlas_class(self, class_name, verify_name, constants): """Return a class type generated as each test generated from the graph atlas""" test_class = type(class_name, (ValveGenerativeBase, ), {**constants}) verify_func = getattr(test_class, verify_name) set_up = self.setup_generator(verify_func) setattr(test_class, 'set_up', set_up) for graphs in self.graphs.values(): for graph in graphs: test_func = self.test_generator([graph]) test_name = 'test_%s' % graph.name setattr(test_class, test_name, test_func) return test_class def generate_atlas_size_class(self, class_name, verify_name, constants): """Return a class type as each test generated from a set of tests in the graph atlas""" test_class = type(class_name, (ValveGenerativeBase, ), {**constants}) verify_func = getattr(test_class, verify_name) set_up = self.setup_generator(verify_func) setattr(test_class, 'set_up', set_up) for num_dps, graph_list in self.graphs.items(): test_func = self.test_generator(graph_list) test_name = 'test_reconfigure_topologies_%s_dps' % num_dps setattr(test_class, test_name, test_func) return test_class def generate_spine_and_leaf_class(self, class_name, verify_name, constants): """Return a class type as each test generated from a set of tests in the graph atlas""" test_class = type(class_name, (ValveGenerativeBase, ), {**constants}) verify_func = getattr(test_class, verify_name) set_up = self.setup_generator(verify_func) setattr(test_class, 'set_up', set_up) curr_nodes = 8 curr_tests = 0 # Iteratively generate spine & leaf networks until `MAX_TESTS` stopping point # By testing all non-isomorphic topologies up to (and including) 7 nodes, # SPINE_NODES + LEAF_NODES <= 7 are already tested # Loop until we have reached a desired number of tests while curr_tests <= self.MAX_TESTS: # Get permutations of numbers that sum to the current number of nodes # The current number of nodes will be split between the two partites of the topology for nodes in ClassGenerator.sums(2, curr_nodes): if 0 in nodes or nodes[0] > nodes[1]: # Ignore empty partites or inverse solutions continue test_name = 'test_%s_%s_spine_and_%s_leaf_topology' % ( curr_tests, nodes[0], nodes[1]) graph = networkx.complete_multipartite_graph(*nodes) test_func = self.test_generator([graph]) setattr(test_class, test_name, test_func) curr_tests += 1 if curr_tests > self.MAX_TESTS: break # Increase current number of nodes curr_nodes += 1 return test_class