def remove_rigid(self): """ Remove rigid links by merging the nodes in place """ while True: for i, j, key, edge in self.edges(data=True, keys=True): # Can't handle duplicate springs if edge["object"] == "rigid": if self.number_of_edges(i, j) != 1: raise RuntimeError( "Cannot have a rigid link across a spring!") bci = "bc" in self.nodes[i] bcj = "bc" in self.nodes[j] if bci and bcj: raise RuntimeError("Cannot merge two nodes with BCs!") self.remove_edge(i, j, key=key) if i < j: if bcj: raise RuntimeError("Internal error: deleting BC") self.replace(nx.contracted_nodes(self, i, j)) else: if bci: raise RuntimeError("Internal error: deleting BC") self.replace(nx.contracted_nodes(self, j, i)) break else: break
def fast_reg_network_unification(graph, index_syn): H = graph.copy() cpt = 0 nodes_size = len(H.nodes()) for n in H.nodes(): #print('for each ' + str(n)) for m in H.nodes(): if n not in m: #print('\tfor each ' + str(m)) if (fast_are_synonyms(n, m, index_syn=index_syn)): key = index_syn[n] if n not in key: #print('\t\t' + str(n) + ' is synonym with ' + str(m)) logging.info('\t\t' + 'merging node ' + str(n) + ' into node ' + str(key)) try: H = nx.contracted_nodes(H, key, n) except: continue if m not in key: logging.info('\t\t' + 'merging node ' + str(m) + ' into node ' + str(key)) try: H = nx.contracted_nodes(H, key, m) except: continue return H
def old_optimal_centrality(G,S,Q,drop_val): ''' Exact calculation of supernode total distance ''' starttime = timeit.default_timer() S = tuple(set(S)) if len(S)==1: superG = G else: superG = nx.contracted_nodes(G,S[0],S[1],self_loops = False) for s in S[2:]: superG = nx.contracted_nodes(superG,S[0],s,self_loops=False) nx.set_node_attributes(superG,False,'seen') q = [S[0]] nx.set_node_attributes(superG,{S[0]:True},'seen') nx.set_node_attributes(superG,{S[0]:0},'level') centrality = 0 while q: curr = q.pop(0) y = superG.nodes[curr]['level'] for n in superG.neighbors(curr): if superG.nodes()[n]['seen']==False: q.append(n) centrality += y+1 if centrality>=drop_val: return drop_val,timeit.default_timer()-starttime nx.set_node_attributes(superG,{n:True},'seen') nx.set_node_attributes(superG,{n:y+1},'level') Q.add_task(S+(2,),centrality) return centrality,timeit.default_timer()-starttime
def squeeze_out_edges(fsa, node_to_order): # checking each node for n in fsa.nodes(): # checking in edges outs = fsa.out_edges(n, data=True) word_to_node = defaultdict(set) for (_, x, data) in outs: if data['attr_dict']['text'] != '': word_to_node[data['attr_dict']['text']].add(x) for word, to_merge in word_to_node.items(): if len(to_merge) <= 1: continue a = list(to_merge)[0] b = list(to_merge)[1] if node_to_order[a] > node_to_order[b]: (a, b) = (b, a) if nx.has_path(fsa, a, b): # split is required new_node = max([k for k in node_to_order]) + 1 fsa.add_node(new_node) fsa.add_edge(new_node, b, key='', attr_dict={'text': ''}) fsa.remove_edge(n, b, key=word) fsa.add_edge(n, new_node, key=word, attr_dict={'text': word}) fsa = nx.contracted_nodes(fsa, a, new_node) clean_up_keys(fsa) else: # split is required # removing the duplicate edge fsa.remove_edge(n, b, key=word) fsa = nx.contracted_nodes(fsa, a, b) clean_up_keys(fsa) return True, fsa return False, fsa
def graph_theory_init(contours): global G for contour in contours: outline = ttfquery.glyph.decomposeOutline(contour, steps=5) outline = round_all(outline) # # char A is a bit special... need to get rid of duplicate points in contours if char == "A" or char == "P" or char == "p" or char == "q": outline = sorted(set(outline),key=outline.index) outline_str = [str(x) for x in outline] # set up the undirected graph with coordinates of outline points as nodes # if the two points on the contour is connected, an edge is added for i in range(len(outline)-1): G.add_node(outline_str[i]) G.add_edge(outline_str[i],outline_str[i+1]) if char == "d": G = nx.contracted_nodes(G,str((38,29)),str((38,28))) if char == "p": G = nx.contracted_nodes(G,str((308,28)),str((308,29))) if char == "h": G.add_edge(str((0,0)),str((0,690))) G.remove_edge(str((0,0)),str((0,433))) if char == "m" or char == "n" or char == "r": G.remove_edge(str((0,0)),str((0,433))) G.add_edge(str((0,0)),str((0,510))) if char == "y": G.remove_edge(str((346,-103)),str((346,77))) # get rid of the self loops: nodes connected to itself G.remove_edges_from(G.selfloop_edges())
def constructMetaTree(G, l_I): metaTree_dict = {} index = 0 # Searching path of type (R, R_V, R') and collapsing them while index < len(l_I): if l_I[index] not in metaTree_dict: metaTree_dict[l_I[index]] = l_I[index] visited = {item: False for item in G.nodes} tempt, find = DFS_metaTree_len2(G, [], visited, l_I[index]) if find: metaTree_dict[tempt[2]] = tempt[0] G.nodes[tempt[0]]['size'] += G.nodes[tempt[2]]['size'] G = nx.contracted_nodes(G, tempt[0], tempt[2], self_loops=False) l_I.remove(tempt[2]) else: index += 1 # Searching cycles and collapsing them index = 0 while index < len(l_I): if l_I[index] not in metaTree_dict: metaTree_dict[l_I[index]] = l_I[index] tempt = [] visited = {item: False for item in G.nodes} [tempt, aux] = DFS_metaTree_cycle(G, tempt, visited, l_I[index], l_I[index], 0) if aux: for i in range(1, len(tempt)): if tempt[i] in l_I: metaTree_dict[tempt[i]] = tempt[0] G.nodes[tempt[0]]['size'] += G.nodes[tempt[i]]['size'] G = nx.contracted_nodes(G, tempt[0], tempt[i], self_loops=False) l_I.remove(tempt[i]) else: index += 1 # Collapsing vulnerable leaves to its neighbor leaf = [ x for x in G.nodes if G.degree[x] == 1 and not G.nodes[x]['immunization'] ] for item in leaf: metaTree_dict[item] = next(G.neighbors(item)) G.nodes[next(G.neighbors(item))]['size'] += G.nodes[item]['size'] G = nx.contracted_nodes(G, next(G.neighbors(item)), item, self_loops=False) target_nodes = [ item for item in G.nodes() if not G.nodes[item]['immunization'] ] for item in target_nodes: metaTree_dict[item] = item return G, metaTree_dict
def contractWarriorZombieDragonPlantRockPyroUsableBeast(G): H = nx.contracted_nodes(G, "[Warrior]", "[Zombie]", self_loops=False) H = nx.contracted_nodes(H, "[Warrior]", "[Dragon]", self_loops=False) H = nx.contracted_nodes(H, "[Warrior]", "[Plant]", self_loops=False) H = nx.contracted_nodes(H, "[Warrior]", "[Rock]", self_loops=False) H = nx.contracted_nodes(H, "[Warrior]", "[Pyro]", self_loops=False) # H = nx.contracted_nodes(H, "[Warrior]", "[UsableBeast]", self_loops=False) return H
def merge_nodes(self, node_id: str, other_graph, merge_properties=None): """ Merge two nodes of the same id belonging to two graphs. Optionally specify merging behavior for individual properties. Common relationships are merged. Example merge properties in Python: { "name":'discard', # keep property of the caller (also if not mentioned in merged_properties) "age":'overwrite', # keep property of the other graph "kids":'combine', # make a list of properties } :param node_id: :param other_graph: other graph object :param merge_properties: :return: """ assert node_id is not None assert other_graph is not None assert other_graph.graph_exists() # find out internal IDs of the two nodes in our graph and other graph real_node = self._find_node(node_id=node_id) real_other_node = self._find_node(node_id=node_id, graph_id=other_graph.graph_id) # save properties of both (by copy) node_props = self.storage.get_graph( self.graph_id).nodes[real_node].copy() other_props = self.storage.get_graph( other_graph.graph_id).nodes[real_other_node].copy() # remember that graphid is ignored in get_graph in this implementation, but respected # in the disjoint implementation # merge the nodes in situ nx.contracted_nodes(self.storage.get_graph(self.graph_id), real_node, real_other_node, copy=False) # deal with properties # remove all properties, including 'contracted' new property self.storage.get_graph(self.graph_id).nodes[real_node].clear() # construct a new set of properties new_props = dict() if merge_properties is None: new_props = node_props else: for k, v in node_props.items(): if k in merge_properties: new_props[k] = node_props[k] if merge_properties[k] == 'discard' else \ other_props[k] if merge_properties[k] == 'overwrite' else \ [node_props[k], other_props[k]] if merge_properties[k] == 'combine' else None else: new_props[k] = node_props[k] self.storage.get_graph( self.graph_id).nodes[real_node].update(new_props)
def contract_nodes(self, dst, src_list=[]): """ @brief Delete all nodes in 'src_list' and connect all the edges that were connected to them to the node 'dst'. @returns nothing. """ for v in src_list: nx.contracted_nodes(self, dst, v, copy=False) # Sometimes nx creates unnecessary self loops... if dst in self.adj[dst]: self.remove_edge(dst, dst)
def constructMetaTree(G, l_I): metaTree_dict = {} index = 0 while index < len(l_I): if l_I[index] not in metaTree_dict: metaTree_dict[l_I[index]] = l_I[index] visited = {item: False for item in G.nodes} tempt, find = DFS_metaTree_len2(G, [], visited, l_I[index]) if find: metaTree_dict[tempt[2]] = tempt[0] G.nodes[tempt[0]]['size'] += G.nodes[tempt[2]]['size'] G = nx.contracted_nodes(G, tempt[0], tempt[2], self_loops=False) l_I.remove(tempt[2]) else: index += 1 index = 0 while index < len(l_I): if l_I[index] not in metaTree_dict: metaTree_dict[l_I[index]] = l_I[index] tempt = [] visited = {item: False for item in G.nodes} [tempt, aux] = DFS_metaTree_cycle(G, tempt, visited, l_I[index], l_I[index], 0) if aux: for i in range(1, len(tempt)): if tempt[i] in l_I: metaTree_dict[tempt[i]] = tempt[0] G.nodes[tempt[0]]['size'] += G.nodes[tempt[i]]['size'] G = nx.contracted_nodes(G, tempt[0], tempt[i], self_loops=False) l_I.remove(tempt[i]) else: index += 1 leaf = [ x for x in G.nodes if G.degree[x] == 1 and not G.nodes[x]['immunization'] ] for item in leaf: metaTree_dict[item] = next(G.neighbors(item)) G.nodes[next(G.neighbors(item))]['size'] += G.nodes[item]['size'] G = nx.contracted_nodes(G, next(G.neighbors(item)), item, self_loops=False) return G, metaTree_dict
def test_contract_selfloop_graph(self): """Tests for node contraction when nodes have selfloops.""" G = nx.cycle_graph(4) G.add_edge(0, 0) actual = nx.contracted_nodes(G, 0, 1) expected = nx.complete_graph([0, 2, 3]) expected.add_edge(0, 0) expected.add_edge(0, 0) assert_edges_equal(actual.edges, expected.edges) actual = nx.contracted_nodes(G, 1, 0) expected = nx.complete_graph([1, 2, 3]) expected.add_edge(1, 1) expected.add_edge(1, 1) assert_edges_equal(actual.edges, expected.edges)
def construct(self): A = np.random.randn(30, 60) B = np.random.randn(60, 10) factors = {'A': A, 'B': B} fg = factor_graph(factors, 'ij,kl->ijkl') h = 2 n = 6 pos = np.zeros((n, 2)) pos[:, 0] = (np.arange(n) - n / 2.0 + 0.5) * h mnx.map_attr('pos', ['i', 'A', 'j', 'k', 'B', 'l'], pos, fg) mng = mnx.ManimGraph(fg, get_fg_node, get_fg_edge_curve) self.add(mng) self.wait(2) fg = combine_variables('j', 'k', fg) pos = np.zeros((n - 1, 2)) pos[:, 0] = (np.arange(n - 1) - (n - 1) / 2.0 + 0.5) * h mnx.map_attr('pos', ['i', 'A', 'j', 'B', 'l'], pos, fg) self.play(*mnx.transform_graph(mng, fg)) fg = fg.copy() fg.nodes['j']['summed'] = True self.play(*mnx.transform_graph(mng, fg)) c = Ellipse(color=GREEN, fill_color=GREEN, fill_opacity=0.3, width=6.5, height=3.5) x, y = fg.nodes['j']['pos'] c.move_to(x * RIGHT + y * DOWN) self.play(FadeIn(c)) self.wait(2) fg = nx.contracted_nodes(fg, 'A', 'j') fg = nx.contracted_nodes(fg, 'A', 'B') fg.node['A']['pos'] = (x, y) fg = nx.relabel_nodes(fg, {'A': 'AB'}) mng.relabel_id(fg, 'A', 'AB') fg.nodes['i']['pos'] = (-2, y) fg.nodes['l']['pos'] = (2, y) self.play(*mnx.transform_graph(mng, fg), Transform(c, get_fg_node('AB', fg))) self.wait(2)
def merge_two_trees(tree_pair1: (nx.Graph, int), tree_pair2: (nx.Graph, int), path: list, main_graph: nx.Graph) -> (nx.Graph, int): """ Merge the given two trees into one tree by using the given path between the two trees. The merged tree is returned. Note that the nodes of the two trees are contracted into one node in the main_graph. This is done to facilitate calculating the min cost paths between other trees in the future. :param tree_pair1: the first tree to merge, consisting of the tree graph and the terminal it represents :param tree_pair2: the second tree to merge, consisting of the tree graph and the terminal it represents :param path: the path from tree1 to tree2 through which the trees are to be merged :param main_graph: the underlying graph (containing both trees) is used to obtain node costs :return: the tree resulting when merging tree1 with tree2 via the given path, and the terminal it represents """ costs = nx.get_node_attributes(main_graph, 'cost') tree1 = tree_pair1[0] tree2 = tree_pair2[0] # draw_trees_to_merge(tree1, tree2, path, main_graph) # first add the path to tree1 prev_node = -1 union_edge = None # this is the edge that joins the connecting path with tree2 for node in path: if tree2.has_node(node): union_edge = (prev_node, node) break # the nodes of tree2 will be added when applying the union of the two trees if not tree1.has_node(node): tree1.add_node(node, cost=costs[node]) if prev_node >= 0: if not tree1.has_edge(prev_node, node): tree1.add_edge(prev_node, node) # contract the newly added nodes in the tree main_graph = nx.contracted_nodes(main_graph, prev_node, node, self_loops=False) prev_node = node # contract all nodes of tree2 in the main graph for node in tree2.nodes(): main_graph = nx.contracted_nodes(main_graph, prev_node, node, self_loops=False) prev_node = node # join tree1 with tree2 (which should be disjoint, and connected with "union_edge") # draw_trees_to_merge(tree1, tree2, path, main_graph) # DEBUG merged_tree = nx.union(tree1, tree2) merged_tree.add_edge(union_edge[0], union_edge[1]) # draw_merged_tree(merged_tree, main_graph) # DEBUG # associate the merged tree with the terminal of the first tree return merged_tree, tree_pair1[1]
def merge_nodes(G,nodes, new_node, attr): G_ = G for i in range(1, len(nodes)): G_ = nx.contracted_nodes(G_, nodes[0], nodes[i], self_loops=False) # Only works for two nodes at a time apparently G__ = nx.relabel.relabel_nodes(G_, {nodes[0] : new_node}) G__.nodes[new_node].update(attr) return G__
def collapse_graph(G, max_T): collapse_dict = {} collapseCC = [] Immunized = [] visited = [False] * G.number_of_nodes() for node in G: if not visited[node]: tempt = [] collapseCC.append( DFS_collapse(G, tempt, visited, node, G.nodes[node]['immunization'])) for item in collapseCC: collapse_dict[item[0]] = item[0] # We check if the collapsing set is targeted or not. if not G.nodes[item[0]]['immunization']: if len(item) == max_T: G.nodes[item[0]]['target'] = True else: G.nodes[item[0]]['target'] = False else: Immunized.append(item[0]) G.nodes[item[0]]['size'] = 1 # We collapse the set of nodes if len(item) > 1: for index in range(1, len(item)): collapse_dict[item[index]] = item[0] G.nodes[item[0]]['size'] += 1 # collapse(G, item[0], item[index], collapse_dict) G = nx.contracted_nodes(G, item[0], item[index], self_loops=False) return G, Immunized, collapse_dict
def simplify_net(network, netx_inp=False): netx = network.network_plot if not netx_inp else network degrees = degree(netx) while True: action = False affected_nodes = set() cliques = sorted(find_cliques(netx), key=lambda c: len(c), reverse=True) if len(cliques) <= 1: # If no more cliques, break break # For each clique for i, clique in enumerate(cliques): clean_clique = check_nodes(affected_nodes, clique) if not clean_clique: # If not clean, pass continue # Contract nodes action = True base = clique[0] affected_nodes.add(base) for j in range(1, len(clique)): netx = contracted_nodes(netx, base, clique[j]) affected_nodes.add(clique[j]) if not action: # If not action in the last pass, done break return netx
def remove_duplicate_locations(self): """Combine fixed nodes that have the same location.""" fixed = [n for n, d in self.graph.nodes().items() if d["fixed"] is True] combine = {} for base_node in fixed: combine[base_node] = [] for other_node in fixed: if ( self.graph.nodes[base_node]["lon"] == self.graph.nodes[other_node]["lon"] and self.graph.nodes[base_node]["lat"] == self.graph.nodes[other_node]["lat"] ): combine[base_node].append(other_node) for base_node, combine_list in combine.items(): for combine_node in combine_list: try: lon = self.graph.nodes[base_node]["lon"] lat = self.graph.nodes[base_node]["lat"] self.graph = nx.contracted_nodes( self.graph, base_node, combine_node, self_loops=False ) self.graph.nodes[base_node]["fixed"] = True self.graph.nodes[base_node]["lon"] = lon self.graph.nodes[base_node]["lat"] = lat except Exception as e: self.log.debug("Already passed {}".format(e)) self.log.info( "Nodes remaining after 'remove_duplicate_locations': {}".format( len(self.graph.nodes) ) )
def merge(self, node_pair): # node_pair: node_new, node # merge node self.data.edge_index[self.data.edge_index == node_pair[0]] = node_pair[1] node_pair = node_pair.cpu().numpy() self.graph = nx.contracted_nodes(self.graph, node_pair[1], node_pair[0]) self.node_par2s.remove(node_pair[0])
def network2nx(x: Union[pd.DataFrame, Iterable], threshold: int = 1, group_by: Union[dict, None] = None) -> nx.DiGraph: """Generates NetworkX graph for neuron connectivity. Parameters ---------- x : pandas.DataFrame Connectivity information: 1. List of edges (columns: 'source', 'target', 'weight') 2. Adjacency matrix (pd.DataFrame, rows=sources, columns=targets) threshold : int, optional Connections weaker than this will be excluded. group_by : None | dict, optional Provide a dictionary ``{group_name: [skid1, skid2, ...]}`` to collapse sets of nodes into groups. Returns ------- networkx.DiGraph NetworkX representation of the network. """ if isinstance(x, pd.DataFrame): miss = [c not in x.columns for c in ['source', 'target', 'weight']] if all(miss): edges = x[['source', 'target', 'weight']].values else: edges = x.reset_index(inplace=False, drop=False).melt(id_vars='index', inplace=False).values elif isinstance(x, (list, np.ndarray)): if any([len(e) != 3 for e in x]): raise ValueError('Edges must be [source, target, weight]') edges = x edges = np.array(edges) if threshold: edges = edges[edges[:, 2] >= threshold] # Generate graph and assign custom properties g = nx.DiGraph() g.add_weighted_edges_from(edges) # Group nodes if group_by: for n, skids in group_by.items(): # First collapse all nodes into the first of each group for s in skids[1:]: g = nx.contracted_nodes(g, str(skids[0]), str(s)) # Now relabel the first node g = nx.relabel_nodes(g, {str(skids[0]): str(n)}) g.nodes[str(n)]['neuron_name'] = str(n) return g
def test_edge_attributes(self): """Tests that node contraction preserves edge attributes.""" # Shape: src1 --> dest <-- src2 G = nx.DiGraph([("src1", "dest"), ("src2", "dest")]) G["src1"]["dest"]["value"] = "src1-->dest" G["src2"]["dest"]["value"] = "src2-->dest" H = nx.MultiDiGraph(G) G = nx.contracted_nodes(G, "src1", "src2") # New Shape: src1 --> dest assert G.edges[("src1", "dest")]["value"] == "src1-->dest" assert (G.edges[("src1", "dest")]["contraction"][( "src2", "dest")]["value"] == "src2-->dest") H = nx.contracted_nodes(H, "src1", "src2") # New Shape: src1 -(x2)-> dest assert len(H.edges(("src1", "dest"))) == 2
def make_acyclic_3(funct_g_2): G_REDUCED_2 = funct_g_2.copy() Super_nodes = {} for i in range(len(G_REDUCED_2.nodes())): Super_nodes[i] = [i] A_Cycle = [] try: A_Cycle = nx.find_cycle(G_REDUCED_2, orientation='original') # print(A_Cycle) except: pass while A_Cycle !=[]: for i in range(len(A_Cycle)-1): # print('i: '+str(i)) # print(A_Cycle) if (A_Cycle[0][0], A_Cycle[i+1][0]) in G_REDUCED_2.edges(): G_REDUCED_2 = nx.contracted_nodes(G_REDUCED_2, A_Cycle[0][0], A_Cycle[i+1][0], self_loops=False) Super_nodes[A_Cycle[0][0]].extend(Super_nodes[A_Cycle[i+1][0]]) Super_nodes[A_Cycle[0][0]] = list(set(Super_nodes[A_Cycle[0][0]])) del Super_nodes[A_Cycle[i+1][0]] else: # break A_Cycle = [] # A_Cycle = nx.find_cycle(G_REDUCED_2, orientation='original') try: A_Cycle = nx.find_cycle(G_REDUCED_2, orientation='original') # print(A_Cycle) except: A_Cycle = [] pass return G_REDUCED_2, Super_nodes
def make_acyclic(G): flag = 0 G_REDUCED = G.copy() Cycles = nx.simple_cycles(G_REDUCED) Cycles_list = list(Cycles) if Cycles_list != []: # print('All cycles are: ' + str(Cycles_list)) flag = 1 else: print('No cycle found.') if flag == 1: while len(max(Cycles_list,key=len))>1: Cycles = nx.simple_cycles(G_REDUCED) Cycles_list = list(Cycles) bigest_Cycle = max(Cycles_list,key=len) # print('Bigest Cycle is: ' + str(bigest_Cycle) + ' with length of ' + str(len(bigest_Cycle))) for i in range(len(bigest_Cycle)-1): G_REDUCED = nx.contracted_nodes(G_REDUCED, bigest_Cycle[0], bigest_Cycle[i+1], self_loops=True) # print('i = '+str(i)) b2 = nx.simple_cycles(G_REDUCED) b2_list = list(b2) # print('All cycles in g_reduced are: ' + str(b2_list)) for i in range(len(b2_list)): G_REDUCED.remove_edge(b2_list[i][0],b2_list[i][0]) return G_REDUCED
def merge_leaf_nodes(graph, head_node=None, quant_active=None, quant_scope=None): """ Traverses the graph, merging those nodes with the same label within the same quantificaton scope. """ if head_node is None: head_node = graph.graph['head_node'] # Get nodes and their scope information. scoped_nodes = get_scoped_nodes(graph, head_node) for (quant_node, expr), nodes_to_merge in scoped_nodes.items(): if len(nodes_to_merge) > 1: master_node, node_type = nodes_to_merge[0] assert node_type == 'leaf' for node, node_type in nodes_to_merge[1:]: # Merge leaves within the same scope: if node_type == 'leaf': graph = nx.contracted_nodes(graph, master_node, node) # Add edges from quantifier to internal function names: elif node_type == 'internal': graph.add_edge(quant_node, node) graph.graph['head_node'] = head_node return graph
def _combine_nodes_in_linked_entities(self): wiki_entities = list() for entity_range in self.sentence_entities.keys(): nodes_to_merge = list() for node in self.graph.nodes(data=True): if any([each[0] >= entity_range[0] and each[1] <= entity_range[1] for each in node[1]['range']]): nodes_to_merge.append(node) wiki_entities.append((self.sentence_entities[entity_range]['uri'], nodes_to_merge)) assert (len(wiki_entities) == len(self.sentence_entities)) for (wiki_id, nodes_to_merge_list) in wiki_entities: if len(nodes_to_merge_list) > 1: for index in range(1, len(nodes_to_merge_list)): self.graph = nx.contracted_nodes(self.graph, nodes_to_merge_list[index][0], nodes_to_merge_list[index - 1][0], self_loops=False) self.graph = nx.relabel.relabel_nodes(self.graph, {nodes_to_merge_list[index][0]: wiki_id}) elif len(nodes_to_merge_list) == 1: self.graph = nx.relabel.relabel_nodes(self.graph, {nodes_to_merge_list[0][0]: wiki_id}) wiki_attribute = {key: {'surfaceform': self.wiki2surfaceform[key]} for key in self.graph.nodes} nx.set_node_attributes(self.graph, wiki_attribute)
def arrange_quantifiers(graph): """ Collapse all quantifier instances into nodes attached to the root. """ head_node = guess_head_node(graph) quant_nodes = [n for n in graph.nodes() if is_quantifier_node(graph, n)] for qn in quant_nodes: # from pudb import set_trace; set_trace() pred_not_quant = find_predecessor_not_quant(graph, qn) term_node = get_term_node_from_quant(graph, qn) graph.add_edge(pred_not_quant, term_node) graph.remove_edge(qn, term_node) for pred in list(graph.predecessors(qn)): graph.remove_edge(pred, qn) graph.add_edge(head_node, qn) q_dict = defaultdict(list) for qn in quant_nodes: q_dict[get_label(graph, qn)].append(qn) for qn_type, nodes in q_dict.items(): if len(nodes) > 1: master_quant_node = nodes[0] for qn in nodes[1:]: graph = nx.contracted_nodes(graph, master_quant_node, qn) return graph
def test_undirected_node_contraction(self): """Tests for node contraction in an undirected graph.""" G = nx.cycle_graph(4) actual = nx.contracted_nodes(G, 0, 1) expected = nx.cycle_graph(3) expected.add_edge(0, 0) assert nx.is_isomorphic(actual, expected)
def test_undirected_node_contraction(self): """Tests for node contraction in an undirected graph.""" G = nx.cycle_graph(4) actual = nx.contracted_nodes(G, 0, 1) expected = nx.complete_graph(3) expected.add_edge(0, 0) assert_true(nx.is_isomorphic(actual, expected))
def merge_two_nodes(self, left_id, right_id): """ remove right node to left node, and right_id will be delete; merge SMILES of these two nodes; add new fragment to self.f2f; update count and frequency in self.f2f """ if self.check_if_merge(left_id, right_id): raw_smiles_left = self.g.nodes[left_id]['smiles'] raw_smiles_right = self.g.nodes[right_id]['smiles'] g2 = nx.contracted_nodes(self.g, left_id, right_id, self_loops=False) merged_result = self._merge_smiles(left_id, right_id) merged_smiles = merged_result['merged_smiles'] g2.nodes[left_id]['smiles'] = merged_smiles g2.nodes[left_id]['mol_inx'] = list(merged_result['merged_inx']) if self.test: print(' >Merged result is: {}'.format(merged_result)) print(' >New network: {}'.format(g2.nodes(data=True))) if merged_smiles not in self.f2f.index: self.f2f.loc[merged_smiles, 'count'] = 0 self.f2f.loc[merged_smiles, 'count'] += 1 self.f2f.loc[raw_smiles_left, 'count'] -= 1 self.f2f.loc[raw_smiles_right, 'count'] -= 1 self.f2f['frequency'] = self.f2f['count'] / self.f2f['count'].sum() self.g = g2.copy()
def _similarity_merge(self, regions, thr=0.65): """ (Private) Procedure that merge similar segments :param regions: The properties of the initially computed regions. :param thr: The threshold for merging. This value depends on the distance considered. """ def _findregion(R): for i in range(len(regions)): if regions[i].label == R: return i for u, v in self._merged_RAG.edges(): Ri = regions[_findregion(u)] Rj = regions[_findregion(v)] sim = self._merged_RAG[u][v]['weight'] if sim >= thr: max_label = Ri if Ri.label > Rj.label else Rj min_label = Ri if Ri.label < Rj.label else Rj for (x, y) in max_label.coords: self._segmentation_merged[(x, y)] = min_label.label self._merged_RAG = contracted_nodes(self._merged_RAG, min_label.label, max_label.label, self_loops=False) return True return False
def _pixels_merge(self, regions, thr_pixels=750): """ (Private) Procedure that merge small segments with their closest neighbor. :param regions: The properties of the initially computed regions. :param thr_pixels: The threshold size for merging. """ def _findregion(R): for i in range(len(regions)): if regions[i].label == R: return i for i in range(len(regions)): Ri = regions[i] lenRi = len(Ri.coords) if (lenRi < thr_pixels): neighbors = list(self._merged_RAG.neighbors(Ri.label)) closest = max( [(regions[_findregion(Rj)].label, self._merged_RAG[ Ri.label][regions[_findregion(Rj)].label]['weight']) for Rj in neighbors], key=lambda x: x[1])[0] Rj = regions[_findregion(closest)] max_label = Ri if Ri.label > Rj.label else Rj min_label = Ri if Ri.label < Rj.label else Rj for (x, y) in max_label.coords: self._segmentation_merged[(x, y)] = min_label.label self._merged_RAG = contracted_nodes(self._merged_RAG, min_label.label, max_label.label, self_loops=False) return True return False
def clean_game_titles_in_graph(G, to_merge, t_names, g_names): for k, v in to_merge.items(): target_node = None source_nodes = [] for node in v: if node in nx.nodes(G): if target_node is None: target_node = node else: source_nodes.append(node) if target_node is not None and len(source_nodes) > 0: for source_node in source_nodes: G = nx.contracted_nodes(G, target_node, source_node) if target_node not in t_names.keys( ) and source_node in t_names.keys(): t_names[target_node] = t_names[source_node] g_names[target_node] = g_names[source_node] del t_names[source_node] del g_names[source_node] total_weight_dict = {} for node in G.nodes(): total_weight = 0.0 for edge in G.edges(node, data=True): total_weight += edge[2]['weight'] total_weight_dict[node] = total_weight nx.set_node_attributes(G, name='total_weight', values=total_weight_dict) return G, list(total_weight_dict.values()), t_names, g_names
def test_multigraph_keys(self): """Tests that multiedge keys are reset in new graph.""" G = nx.path_graph(3, create_using=nx.MultiGraph()) G.add_edge(0, 1, 5) G.add_edge(0, 0, 0) G.add_edge(0, 2, 5) actual = nx.contracted_nodes(G, 0, 2) expected = nx.MultiGraph() expected.add_edge(0, 1, 0) expected.add_edge(0, 1, 5) expected.add_edge(0, 1, 2) # keyed as 2 b/c 2 edges already in G expected.add_edge(0, 0, 0) expected.add_edge(0, 0, 1) # this comes from (0, 2, 5) assert_edges_equal(actual.edges, expected.edges)
def test_create_multigraph(self): """Tests that using a MultiGraph creates multiple edges.""" G = nx.path_graph(3, create_using=nx.MultiGraph()) G.add_edge(0, 1) G.add_edge(0, 0) G.add_edge(0, 2) actual = nx.contracted_nodes(G, 0, 2) expected = nx.MultiGraph() expected.add_edge(0, 1) expected.add_edge(0, 1) expected.add_edge(0, 1) expected.add_edge(0, 0) expected.add_edge(0, 0) assert_edges_equal(actual.edges, expected.edges)
def test_node_attributes(self): """Tests that node contraction preserves node attributes.""" G = nx.cycle_graph(4) # Add some data to the two nodes being contracted. G.node[0] = dict(foo='bar') G.node[1] = dict(baz='xyzzy') actual = nx.contracted_nodes(G, 0, 1) # We expect that contracting the nodes 0 and 1 in C_4 yields K_3, but # with nodes labeled 0, 2, and 3, and with a self-loop on 0. expected = nx.complete_graph(3) expected = nx.relabel_nodes(expected, {1: 2, 2: 3}) expected.add_edge(0, 0) expected.node[0] = dict(foo='bar', contraction={1: dict(baz='xyzzy')}) assert_true(nx.is_isomorphic(actual, expected)) assert_equal(actual.node, expected.node)
def cleanRedundantNodes(DG, trajectories_data_f): while 1: #join trajectories that only has as parent and child each other. (A->B->C) same_nodes = [] for ind1 in DG.nodes(): next_nodes = DG.successors(ind1) if len(next_nodes) == 1: pp = DG.predecessors(next_nodes[0]); if len(pp) == 1 and pp[0] == ind1 and ind1!=next_nodes[0]: same_nodes.append((ind1, next_nodes[0])) if len(same_nodes) == 0: break for ind1, ind2 in same_nodes: DG = nx.contracted_nodes(DG, ind1, ind2) row2chg = trajectories_data_f.worm_index_auto == ind2 trajectories_data_f.loc[row2chg, 'worm_index_auto'] = ind1 return DG, trajectories_data_f
def edge_function(G,M,Forest,unmarked_edges,tree_to_root,tree_num_of_v,root_of_v,v,Blossom_stack,e): e2 = (e[1],e[0]) #the edge in the other order if ((e in unmarked_edges or e2 in unmarked_edges) and e!=[]): w = e[1] # the other vertex of the unmarked edge w_in_Forest = 0; ##Indicator for w in F or not ##Go through all the trees in the forest to check if w in F tree_of_w = None tree_num_of_w = None for tree_number in xrange(len(Forest)): tree = Forest[tree_number] if tree.has_node(w) == True: w_in_Forest = 1 root_of_w = tree_to_root[tree_number] tree_num_of_w = tree_number tree_of_w = Forest[tree_num_of_w] break #Break the outer for loop if w_in_Forest == 0: ## w is matched, so add e and w's matched edge to F Forest[tree_num_of_v].add_edge(e[0],e[1]) # edge {v,w} # print "edge added to forest: ", e # Note: we don't add w to forest nodes b/c it's odd dist from root # assert(M.has_node(w)) edge_w = list(M.edges(w))[0] # get edge {w,x} return (1,edge_w) ## store to add to forest after parallel for else: ## w is in Forest # if odd, do nothing. if dist_to_root(w,root_of_w,Forest[tree_num_of_w])%2 == 1: #CASE 4 return (4,0) if dist_to_root(w,root_of_w,Forest[tree_num_of_w])%2 == 0: if (tree_num_of_v != tree_num_of_w): ##Shortest path from root(v)--->v-->w---->root(w) path_in_v = nx.shortest_path(Forest[tree_num_of_v], source = root_of_v, target = v) path_in_w = nx.shortest_path(Forest[tree_num_of_w], source = w, target = root_of_w) return (2,path_in_v + path_in_w) else: ##Contract the blossom # create blossom blossom = nx.shortest_path(tree_of_w, source=v, target=w) blossom.append(v) # assert(len(blossom)%2 == 0) # contract blossom into single node w contracted_G = copy.deepcopy(G) contracted_M = copy.deepcopy(M) for node in blossom[0:len(blossom)-1]: if node != w: contracted_G = nx.contracted_nodes(contracted_G, w, node, self_loops=False) if node in contracted_M.nodes(): edge_rm = list(M.edges(node))[0] #this will be exactly one edge contracted_M.remove_node(node) contracted_M.remove_node(edge_rm[1]) # assert(len(list(contracted_M.nodes()))%2 == 0) # add blossom to our stack Blossom_stack.append(w) # recurse aug_path = finding_aug_path(contracted_G, contracted_M, Blossom_stack) # check if blossom exists in aug_path v_B = Blossom_stack.pop() if (v_B in aug_path): ##Define the L_stem and R_stem L_stem = aug_path[0:aug_path.index(v_B)] R_stem = aug_path[aug_path.index(v_B)+1:] lifted_blossom = [] #stores the path within the blossom to take # Find base of blossom i = 0 base = None base_idx = -1 blossom_ext = blossom + [blossom[1]] while base == None and i < len(blossom) - 1: if not(M.has_edge(blossom[i],blossom[i+1])): if not(M.has_edge(blossom[i+1],blossom_ext[i+2])): base = blossom[i+1] base_idx = i+1 else: i += 2 else: i += 1 # if needed, create list of blossom nodes starting at base if blossom[0] != base: based_blossom = [] base_idx = blossom.index(base) for i in xrange(base_idx,len(blossom)-1): based_blossom.append(blossom[i]) for i in xrange(0,base_idx): based_blossom.append(blossom[i]) based_blossom.append(base) else: based_blossom = blossom # CHECK IF BLOSSOM IS ENDPT if L_stem == [] or R_stem == []: if L_stem != []: if G.has_edge(base, L_stem[-1]): # CASE 1: # Chuck the blossom. return L_stem + [base] else: # CASE 2: # find where Lstem is connected i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] else: # opposite dir path lifted_blossom = based_blossom[i:] i += 1 return (3,L_stem + lifted_blossom) else: if G.has_edge(base, R_stem[0]): # CASE 1: # Chuck the blossom. return (3,[base] + R_stem) else: # CASE 2: # find where R_stem is connected i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] i += 1 return (3,lifted_blossom + R_stem) else: # blossom is in the middle # LIFT the blossom # check if L_stem attaches to base if M.has_edge(base, L_stem[-1]): # find where right stem attaches if G.has_edge(base, R_stem[0]): # blossom is useless return (3,L_stem + [base] + R_stem) else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] # print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] # print lifted_blossom i += 1 return (3,L_stem + lifted_blossom + R_stem) else: # R stem to base is in matching # assert(M.has_edge(base, R_stem[0])) # check where left stem attaches if G.has_edge(base, L_stem[-1]): # blossom is useless return (3,L_stem + [base] + R_stem) else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] else: # opposite dir path lifted_blossom = based_blossom[i:] i += 1 return (3,L_stem + list((lifted_blossom)) + R_stem) else: # blossom is not in aug_path return (3,aug_path)
def finding_aug_path(G,M,Blossom_stack=[]): Forest = [] #Storing the Forests Path = [] # The final path unmarked_edges = list(set(G.edges()) - set(M.edges())) unmarked_nodes = list(G.nodes()) Forest_nodes = [] ## we need a map from v to the tree tree_to_root = {} # key=idx of tree in forest, val=root root_to_tree = {} # key=root, val=idx of tree in forest ##List of exposed vertices - ROOTS OF TREES exp_vertex = list(set(G.nodes()) - set(M.nodes())) counter = 0 #List of trees with the exposed vertices as the roots for v in exp_vertex: temp = nx.Graph() temp.add_node(v) Forest.append(temp) Forest_nodes.append(v) #link each root to its tree tree_to_root[counter] = v root_to_tree[v] = counter counter = counter + 1 for v in Forest_nodes: root_of_v = None tree_num_of_v = None for tree_number in xrange(len(Forest)): tree_in = Forest[tree_number] if tree_in.has_node(v) == True: root_of_v = tree_to_root[tree_number] tree_num_of_v = tree_number break #Break out of the for loop edges_v = list(G.edges(v)) for edge_number in xrange(len(edges_v)): e = edges_v[edge_number] e2 = (e[1],e[0]) #the edge in the other order if ((e in unmarked_edges or e2 in unmarked_edges) and e!=[]): w = e[1] # the other vertex of the unmarked edge w_in_Forest = 0; ##Indicator for w in F or not ##Go through all the trees in the forest to check if w in F tree_of_w = None tree_num_of_w = None for tree_number in xrange(len(Forest)): tree = Forest[tree_number] if tree.has_node(w) == True: w_in_Forest = 1 root_of_w = tree_to_root[tree_number] tree_num_of_w = tree_number tree_of_w = Forest[tree_num_of_w] break #Break the outer for loop if w_in_Forest == 0: ## w is matched, so add e and w's matched edge to F Forest[tree_num_of_v].add_edge(e[0],e[1]) # edge {v,w} # Note: we don't add w to forest nodes b/c it's odd dist from root #assert(M.has_node(w)) edge_w = list(M.edges(w))[0] # get edge {w,x} Forest[tree_num_of_v].add_edge(edge_w[0],edge_w[1]) # add edge{w,x} Forest_nodes.append(edge_w[1]) ## add {x} to the list of forest nodes else: ## w is in Forest # if odd, do nothing. if dist_to_root(w,root_of_w,Forest[tree_num_of_w])%2 == 0: if (tree_num_of_v != tree_num_of_w): ##Shortest path from root(v)--->v-->w---->root(w) path_in_v = nx.shortest_path(Forest[tree_num_of_v], source = root_of_v, target = v) path_in_w = nx.shortest_path(Forest[tree_num_of_w], source = w, target = root_of_w) return path_in_v + path_in_w else: ##Contract the blossom # create blossom blossom = nx.shortest_path(tree_of_w, source=v, target=w) blossom.append(v) #assert(len(blossom)%2 == 0) # contract blossom into single node w contracted_G = copy.deepcopy(G) contracted_M = copy.deepcopy(M) for node in blossom[0:len(blossom)-1]: if node != w: contracted_G = nx.contracted_nodes(contracted_G, w, node, self_loops=False) if node in contracted_M.nodes(): edge_rm = list(M.edges(node))[0] #this will be exactly one edge contracted_M.remove_node(node) contracted_M.remove_node(edge_rm[1]) #assert(len(list(contracted_M.nodes()))%2 == 0) # add blossom to our stack Blossom_stack.append(w) # recurse aug_path = finding_aug_path(contracted_G, contracted_M, Blossom_stack) # check if blossom exists in aug_path v_B = Blossom_stack.pop() if (v_B in aug_path): ##Define the L_stem and R_stem L_stem = aug_path[0:aug_path.index(v_B)] R_stem = aug_path[aug_path.index(v_B)+1:] lifted_blossom = [] #stores the path within the blossom to take # Find base of blossom i = 0 base = None base_idx = -1 blossom_ext = blossom + [blossom[1]] while base == None and i < len(blossom) - 1: if not(M.has_edge(blossom[i],blossom[i+1])): if not(M.has_edge(blossom[i+1],blossom_ext[i+2])): base = blossom[i+1] base_idx = i+1 else: i += 2 else: i += 1 # if needed, create list of blossom nodes starting at base if blossom[0] != base: based_blossom = [] base_idx = blossom.index(base) for i in xrange(base_idx,len(blossom)-1): based_blossom.append(blossom[i]) for i in xrange(0,base_idx): based_blossom.append(blossom[i]) based_blossom.append(base) else: based_blossom = blossom # CHECK IF BLOSSOM IS ENDPT if L_stem == [] or R_stem == []: if L_stem != []: if G.has_edge(base, L_stem[-1]): # CASE 1: # Chuck the blossom return L_stem + [base] else: # CASE 2: # find where Lstem is connected i = 1 while (lifted_blossom == []): #assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] #################### else: # opposite dir path lifted_blossom = based_blossom[i:]########################## i += 1 return L_stem + lifted_blossom else: if G.has_edge(base, R_stem[0]): # CASE 1: # Chuck the blossom. return [base] + R_stem else: # CASE 2: # find where R_stem is connected i = 1 while (lifted_blossom == []): #assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] #print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] i += 1 return lifted_blossom + R_stem else: # blossom is in the middle # LIFT the blossom # check if L_stem attaches to base if M.has_edge(base, L_stem[-1]): # find where right stem attaches if G.has_edge(base, R_stem[0]): # blossom is useless return L_stem + [base] + R_stem else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] # print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] # print lifted_blossom i += 1 return L_stem + lifted_blossom + R_stem else: # R stem to base is in matching # assert(M.has_edge(base, R_stem[0])) # check where left stem attaches if G.has_edge(base, L_stem[-1]): # blossom is useless return L_stem + [base] + R_stem else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] else: # opposite dir path lifted_blossom = based_blossom[i:] i += 1 return L_stem + list((lifted_blossom)) + R_stem else: # blossom is not in aug_path return aug_path ##IF Nothing is Found return Path ##Empty Path
def test_without_self_loops(self): """Tests for node contraction without preserving self-loops.""" G = nx.cycle_graph(4) actual = nx.contracted_nodes(G, 0, 1, self_loops=False) expected = nx.complete_graph(3) assert_true(nx.is_isomorphic(actual, expected))
def finding_aug_path(G,M,Blossom_stack=[]): Forest = [] #Storing the Trees Path = [] # The final path unmarked_edges = list(set(G.edges()) - set(M.edges())) unmarked_nodes = list(G.nodes()) Forest_nodes = [] ## we need a map from v to the tree tree_to_root = {} # key=idx of tree in forest, val=root root_to_tree = {} # key=root, val=idx of tree in forest ##List of exposed vertices - ROOTS OF TREES exp_vertex = list(set(G.nodes()) - set(M.nodes())) counter = 0 #List of trees with the exposed vertices as the roots for v in exp_vertex: ######## could be parallelized temp = nx.Graph() temp.add_node(v) Forest.append(temp) Forest_nodes.append(v) #link each root to its tree tree_to_root[counter] = v root_to_tree[v] = counter counter = counter + 1 for v in Forest_nodes: root_of_v = None tree_num_of_v = None for tree_number in xrange(len(Forest)): ######## could be parallelized # find tree of v tree_in = Forest[tree_number] if tree_in.has_node(v) == True: root_of_v = tree_to_root[tree_number] tree_num_of_v = tree_number break #Break out of the for loop edges_v = list(G.edges(v)) pool = Pool(processes = 4) edge_data = edges_v # Feed the function all global args partial_edge = partial(edge_function,G,M,Forest,unmarked_edges,tree_to_root,tree_num_of_v,root_of_v,v,Blossom_stack) #PARALLEL LOOP! temp = pool.map(partial_edge, edge_data) pool.terminate() for i in xrange(len(temp)): ######## could be parallelized if temp[i] != None and (temp[i][0] == 2 or temp[i][0] == 3): return temp[i][1] # Not CASE 2 or 3 ## check for blossoms of 3-length for i in xrange(len(temp)): ######## could be parallelized if temp[i] != None and (temp[i][0] == 1 and G.has_edge(v,temp[i][1][1])): #contract len 3 blossom w = temp[i][1][0] blossom = [v,w,temp[i][1][1],v] contracted_G = copy.deepcopy(G) contracted_M = copy.deepcopy(M) for node in blossom[0:len(blossom)-1]: if node != w: contracted_G = nx.contracted_nodes(contracted_G, w, node, self_loops=False) if node in contracted_M.nodes(): edge_rm = list(M.edges(node))[0] #this will be exactly one edge contracted_M.remove_node(node) contracted_M.remove_node(edge_rm[1]) # assert(len(list(contracted_M.nodes()))%2 == 0) # add blossom to our stack Blossom_stack.append(w) # recurse aug_path = finding_aug_path(contracted_G, contracted_M, Blossom_stack) # check if blossom exists in aug_path v_B = Blossom_stack.pop() if (v_B in aug_path): ##Define the L_stem and R_stem L_stem = aug_path[0:aug_path.index(v_B)] R_stem = aug_path[aug_path.index(v_B)+1:] lifted_blossom = [] #stores the path within the blossom to take # Find base of blossom i = 0 base = None base_idx = -1 blossom_ext = blossom + [blossom[1]] while base == None and i < len(blossom) - 1: if not(M.has_edge(blossom[i],blossom[i+1])): if not(M.has_edge(blossom[i+1],blossom_ext[i+2])): base = blossom[i+1] base_idx = i+1 else: i += 2 else: i += 1 # if needed, create list of blossom nodes starting at base if blossom[0] != base: based_blossom = [] base_idx = blossom.index(base) for i in xrange(base_idx,len(blossom)-1): based_blossom.append(blossom[i]) for i in xrange(0,base_idx): based_blossom.append(blossom[i]) based_blossom.append(base) else: based_blossom = blossom # CHECK IF BLOSSOM IS ENDPT if L_stem == [] or R_stem == []: if L_stem != []: if G.has_edge(base, L_stem[-1]): # CASE 1: # Chuck the blossom return L_stem + [base] else: # CASE 2: # find where Lstem is connected i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] else: # opposite dir path lifted_blossom = based_blossom[i:] i += 1 return L_stem + lifted_blossom else: # R is not empty, L is empty if G.has_edge(base, R_stem[0]): # CASE 1: # Chuck the blossom. return [base] + R_stem else: # CASE 2: # find where R_stem is connected i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] # print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] i += 1 return lifted_blossom + R_stem else: # blossom is in the middle # LIFT the blossom # check if L_stem attaches to base if M.has_edge(base, L_stem[-1]): # find where right stem attaches if G.has_edge(base, R_stem[0]): # blossom is useless return L_stem + [base] + R_stem else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],R_stem[0]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = based_blossom[:i+1] print lifted_blossom else: # opposite dir path lifted_blossom = list(reversed(based_blossom))[:-i] print lifted_blossom i += 1 return L_stem + lifted_blossom + R_stem else: # R stem to base is in matching assert(M.has_edge(base, R_stem[0])) # check where left stem attaches if G.has_edge(base, L_stem[-1]): # blossom is useless return L_stem + [base] + R_stem else: # blossom needs to be lifted i = 1 while (lifted_blossom == []): # assert(i < len(based_blossom)-1) if G.has_edge(based_blossom[i],L_stem[-1]): # make sure we're adding the even part to lifted path if i%2 == 0: # same dir path lifted_blossom = list(reversed(based_blossom))[-i-1:] else: # opposite dir path lifted_blossom = based_blossom[i:] i += 1 return L_stem + list((lifted_blossom)) + R_stem else: # blossom is not in aug_path return aug_path for i in xrange(len(temp)): if temp[i] != None and temp[i][0] ==1: Forest[tree_num_of_v].add_edge(v,temp[i][1][0]) Forest[tree_num_of_v].add_edge(temp[i][1][0],temp[i][1][1]) Forest_nodes.append(temp[i][1][1]) return [] #Empty Path