def ordered_items(self): ''' Yields this graph's nodes and keys in a guaranteed consistent order. First: The (weakly) connected components of the graph are put in a list. The components are then sorted by the minimum (lexicographically-speaking) key they contain. Then, the tree's RNG seed is used to shuffle the connected components. A few notes: + The components are randomized because strange behavior might occur if the nodes are left to be in the same order produced by normal iteration. That would make the resulting graph look ugly. + The user can set the tree's seed field to help obtain the same result every time the program is run on the same input. The user can also change the seed to change the layout instead of fiddling around with the drawn tree itself. + The components are sorted even though they are then immediately shuffled again. This is to ensure the rng.shuffle function produces the same result for the same seed. Second: The keys and node dictionaries for all of the nodes in all of the components are then returned in lexicographical order. ''' components = weakly_connected_components(self.graph) components = sorted(components, key=lambda component: min(component, key=str)) rng = random.Random(self.seed) rng.shuffle(components) for component in components: for key in sorted(component, key=str): yield key, self[key]
def g_treedoubling(g, exact_algo=held_karp, beta=1.0): # 1. Dividing the graph into components best_msa = None best_k = len(g) for start_node in g: msa = calc_msa(g, start_node) one_way_edge_count = len(list(find_one_way_edges(msa.edges, g, beta))) if one_way_edge_count < best_k: best_msa = msa best_k = one_way_edge_count msa = best_msa one_way_edges = list(find_one_way_edges(msa.edges, g, beta)) # degenerate case: no one-way edges in msa => just do tree doubling if not one_way_edges: start_node = next(iter(g.nodes)) tour = component_path(msa, g.nodes, start_node, start_node) tour = metric_shortcut(tour) return {'cost': tour_cost(tour, g), 'tour': tour, 'kernel_size': 0} for u, v in one_way_edges: msa.remove_edge(u, v) components = list(weakly_connected_components(msa)) # 2. Finding a tour of the components meta_graph = nx.DiGraph() for (c1, nodes_1), (c2, nodes_2) in itertools.permutations( enumerate(components), 2): min_edge = cheapest_edge_between(nodes_1, nodes_2, g) # preserve a reference to the original edge u, v = min_edge meta_graph.add_edge(c1, c2, weight=g[u][v]['weight'], original=min_edge) meta_tour = exact_algo(meta_graph)['tour'] in_nodes, out_nodes = get_in_and_out_nodes(meta_tour, meta_graph) # 3. Finding a Hamilton path for each component eulerian_trails = [ component_path(msa, comp_nodes, in_node, out_node) for comp_nodes, in_node, out_node in zip( components, in_nodes, out_nodes) ] # 4. Combining the component tour with the paths tour = [] for comp_index in meta_tour: tour += eulerian_trails[comp_index] tour = metric_shortcut(tour) return { 'cost': tour_cost(tour, g), 'tour': tour, 'kernel_size': len(one_way_edges) }
def mark_families(self): ''' Mark all families in the tree by adding a 'family' attribute to each Member node, which is a dictionary shared by all members of that family. ''' # Families are weakly connected components of the members-only graph members_only = self.member_subgraph() families = weakly_connected_components(members_only) # Add a pointer to each member's family subgraph for family in families: family_dict = {} for key in family: self[key]['family'] = family_dict
from networkx.algorithms.components import weakly_connected_components, strongly_connected_components with open('graph-components.txt') as f: lines = f.readlines() edgeList = [line.strip().split() for line in lines] G = nx.DiGraph() G.add_edges_from(edgeList) figure(figsize=(14, 6)) ax = plt.subplot(1, 3, 1) ax.title.set_text("Input graph ") nx.draw_networkx(G) weak_components = weakly_connected_components(G) strong_components = strongly_connected_components(G) W = [G.subgraph(c).copy() for c in weakly_connected_components(G)] S = [G.subgraph(c).copy() for c in strongly_connected_components(G)] weak_component = max(W, key=len) strong_component = max(S, key=len) ax = plt.subplot(1, 3, 2) ax.title.set_text("Weakly Connected Components ") pos = nx.spring_layout(weak_component) nx.draw_networkx(weak_component) ax = plt.subplot(1, 3, 3) ax.title.set_text("Strongly Connected Components ")
import networkx as nx import matplotlib.pyplot as plt import random from networkx.algorithms.components import weakly_connected_components colorlist = ['r', 'g', 'b', 'y', 'c', 'm', 'k'] g = nx.read_gexf('../../dataset/graph-small/graph.gexf') wcc_subgraphs = [g.subgraph(wcc) for wcc in weakly_connected_components(g)] # There are 7 weakly connected components and we are plotting the three biggest ones # that represent customers of a specific store. They all have transaction at that POS device. for i, subgraph in enumerate(wcc_subgraphs): randIndex = random.randint(0, len(colorlist) - 1) if(len(subgraph.nodes()) > 10): plt.subplot(2, 2, i+1) nx.draw(subgraph, node_color=colorlist[randIndex]) plt.show()