def test_maximal_matching(): graph = nx.Graph() graph.add_edge(0, 1) graph.add_edge(0, 2) graph.add_edge(0, 3) graph.add_edge(0, 4) graph.add_edge(0, 5) graph.add_edge(1, 2) matching = nx.maximal_matching(graph) vset = set(u for u, v in matching) vset = vset | set(v for u, v in matching) for edge in graph.edges_iter(): u, v = edge ok_(len(set([v]) & vset) > 0 or len(set([u]) & vset) > 0, "not a proper matching!") eq_(1, len(matching), "matching not length 1!") graph = nx.Graph() graph.add_edge(1, 2) graph.add_edge(1, 5) graph.add_edge(2, 3) graph.add_edge(2, 5) graph.add_edge(3, 4) graph.add_edge(3, 6) graph.add_edge(5, 6) matching = nx.maximal_matching(graph) vset = set(u for u, v in matching) vset = vset | set(v for u, v in matching) for edge in graph.edges_iter(): u, v = edge ok_(len(set([v]) & vset) > 0 or len(set([u]) & vset) > 0, "not a proper matching!")
def min_maximal_matching(G): """Returns the minimum maximal matching of G. That is, out of all maximal matchings of the graph G, the smallest is returned. Parameters ---------- G : NetworkX graph Undirected graph Returns ------- min_maximal_matching : set Returns a set of edges such that no two edges share a common endpoint and every edge not in the set shares some common endpoint in the set. Cardinality will be 2*OPT in the worst case. Notes ----- The algorithm computes an approximate solution fo the minimum maximal cardinality matching problem. The solution is no more than 2 * OPT in size. Runtime is O(|E|). References ---------- .. [1] Vazirani, Vijay Approximation Algorithms (2001) """ return nx.maximal_matching(G)
def f37(self): start = 0 s = nx.maximal_matching(self.G) res = len(s) stop = 0 # self.feature_time.append(stop - start) return res
def minleaf(G, start): dag = __class__.get_dag(G, start) GG = nx.Graph() GG.add_nodes_from(G) GG.add_edges_from(dag) B = nx.DiGraph() tgt_dict = dict() mm_tgt_set = set() tmin = [] for edge in dag: src = edge[0] tgt = (edge[1][0] + 100, edge[1][1] + 100) tgt_dict.setdefault(tgt, []).append(src) B.add_edge(src, tgt) mm = nx.maximal_matching(B) for edge in mm: mm_tgt_set.add(edge[1]) for node in tgt_dict: if node not in mm_tgt_set: mm.add((tgt_dict[node][0], node)) for edge in mm: tgt = (edge[1][0] - 100, edge[1][1] - 100) assert tgt[0] >= 0 and tgt[1] >= 0 tmin.append((edge[0], tgt)) return tmin, dag
def is_subtree(G, u, H, w, subtree): G_childs = G.childrenOf[u] H_childs = H.childrenOf[w] # If the subtrees don't have the same number of children, they can't # possibly be isomorphic if len(G_childs) != len(H_childs): subtree[(u, w)] = False else: print G.G.edges(), H.G.edges(), u, w edgeSet = [] for ui in G_childs: for wi in H_childs: edge = (ui, wi) if edge in subtree and subtree[edge] == True: edgeSet.append(edge) bg = nx.Graph() bg.add_nodes_from(G_childs, bipartite=0) bg.add_nodes_from(H_childs, bipartite=1) bg.add_edges_from(edgeSet) print bg.nodes(), bg.edges() matchingSize = len(nx.maximal_matching(bg)) if matchingSize == (len(bg.nodes()) / 2): # perfect matching for bg subtree[(u, w)] = True
def generate_coarser_graph(G, level): if G.number_of_nodes() <= 2: return G, level # sort the edges col[level] = {} edges[level] = {} mie = nx.maximal_matching(G) if (len(mie)) == 0: return G, level for i in mie: new_node = "{0}-{1}".format(i[0], i[1]) G.add_node(new_node) col[level][new_node] = list(i) c1, c2 = i[0], i[1] cn1, cn2 = list(G.adj[c1]), list(G.adj[c2]) G.remove_node(c1) G.remove_node(c2) edges[level][new_node] = [] for i in cn1: if i == c1 or i == c2: continue G.add_edge(i, new_node) edges[level][new_node].append((i, c1)) for i in cn2: if i == c1 or i == c2: continue G.add_edge(i, new_node) edges[level][new_node].append((i, c2)) return generate_coarser_graph(G, level + 1)
def test_maximal_matching_ordering(): # check edge ordering G = nx.Graph() G.add_nodes_from([100, 200, 300]) G.add_edges_from([(100, 200), (100, 300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) G = nx.Graph() G.add_nodes_from([200, 100, 300]) G.add_edges_from([(100, 200), (100, 300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) G = nx.Graph() G.add_nodes_from([300, 200, 100]) G.add_edges_from([(100, 200), (100, 300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1)
def compute_features(self): self.add_feature( "maximal_matching", lambda graph: len(nx.maximal_matching(graph)), "Maximal matching", InterpretabilityScore(4), )
def test_maximal_matching_ordering(): # check edge ordering G = nx.Graph() G.add_nodes_from([100,200,300]) G.add_edges_from([(100,200),(100,300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) G = nx.Graph() G.add_nodes_from([200,100,300]) G.add_edges_from([(100,200),(100,300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) G = nx.Graph() G.add_nodes_from([300,200,100]) G.add_edges_from([(100,200),(100,300)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1)
def test_self_loops(self): # Create the path graph with two self-loops. G = nx.path_graph(3) G.add_edges_from([(0, 0), (1, 1)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) # The matching should never include self-loops. assert_false(any(u == v for u, v in matching)) assert_true(nx.is_maximal_matching(G, matching))
def calculate_mcm(graph): G = nx.Graph() for v in graph: G.add_node(str(v)) for v in graph: for e in graph[v]: G.add_edge(str(v), str(e)) return [(int(left), int(right)) for left, right in nx.maximal_matching(G)]
def run_mechanism(self): k_max = max(int(self.B_depart[-1]//self.d), int(self.S_depart[-1]//self.d)) B_alive_idx = np.array([],dtype=int) #Store indices of alive buy bids S_alive_idx = np.array([],dtype=int) #Store indices of alive sell bids B_current = 0 S_current = 0 G = nx.DiGraph() for k in range(k_max): start = k*self.d end = (k+1) * self.d # Remove departing bids if B_alive_idx.size != 0: B_depart_idx = B_alive_idx[np.where(self.B_depart[B_alive_idx] <= end)] B_alive_idx = np.setdiff1d(B_alive_idx,B_depart_idx) for b in B_depart_idx: if (-b-1) in G: G.remove_node(-b-1) if S_alive_idx.size != 0: S_depart_idx = S_alive_idx[np.where(self.S_depart[S_alive_idx] <= end)] S_alive_idx = np.setdiff1d(S_alive_idx,S_depart_idx) for s in S_depart_idx: if (s+1) in G: G.remove_node(s+1) # Add arriving bids while B_current < len(self.B) and self.B_arrival[B_current] <= end: B_alive_idx = np.append(B_alive_idx,B_current) S_candidates = S_alive_idx[np.where(self.S[S_alive_idx] <= self.B[B_current])] for s in S_candidates: G.add_edge(s+1, -B_current-1) B_current = B_current + 1 while S_current < len(self.S) and self.S_arrival[S_current] <= end: S_alive_idx = np.append(S_alive_idx,S_current) B_candidates = B_alive_idx[np.where(self.B[B_alive_idx] >= self.S[S_current])] for b in B_candidates: G.add_edge(S_current+1, -b-1) S_current = S_current + 1 # Clear matching M_new = nx.maximal_matching(G) M_num_new = len(M_new) if np.array(list(M_new)).size != 0: S_M_new = np.array(list(M_new))[:,0]-1 B_M_new = -np.array(list(M_new))[:,1]-1 self.B_M = np.hstack((self.B_M, B_M_new)) self.S_M = np.hstack((self.S_M, S_M_new)) self.M_num = self.M_num + M_num_new B_alive_idx = np.setdiff1d(B_alive_idx, B_M_new) G.remove_nodes_from(-B_M_new-1) S_alive_idx = np.setdiff1d(S_alive_idx, S_M_new) G.remove_nodes_from(S_M_new-1) return self.B[self.B_M], self.S[self.S_M]
def maximal_matching(nodes, edges): g = nx.from_edgelist(edges) mat = nx.maximal_matching(g) weight = np.zeros(len(g.edges)) k = 0 for e in g.edges: if e in mat: weight[k] = 1 k += 1 return weight
def test_ordering(self): """Tests that a maximal matching is computed correctly regardless of the order in which nodes are added to the graph. """ for nodes in permutations(range(3)): G = nx.Graph() G.add_nodes_from(nodes) G.add_edges_from([(0, 1), (0, 2)]) matching = nx.maximal_matching(G) assert_equal(len(matching), 1) assert_true(nx.is_maximal_matching(G, matching))
def Maximal_matching(grafo): tiempo=[] for i in range(30): tiempo_inicial = dt.datetime.now() for j in range(1000): nx.maximal_matching(grafo) tiempo_final = dt.datetime.now() tiempo_ejecucion = (tiempo_final - tiempo_inicial).total_seconds() tiempo.append(tiempo_ejecucion) media=nup.mean(tiempo) desv=nup.std(tiempo) mediana=nup.median(tiempo) datos["algoritmo"].append("Maximal_matching") datos["grafo"].append(grafo.name) datos["cant_vertice"].append(grafo.number_of_nodes()) datos["cant_arista"].append(grafo.number_of_edges()) datos["media"].append(media) datos["desv"].append(desv) datos["mediana"].append(mediana) return datos
def gen_edges(self, graph): # Split Cv and generate alias graph if not self.a_graph: self.a_graph = self.split(graph) # Solve max matching to obtain round queue = nx.maximal_matching(self.a_graph) # Cull active edges self.a_graph.remove_edges_from(queue) # Reassociate aliases return [(e[0].org, e[1].org) for e in queue]
def rank_maximal_allocation(G, agent_cap=None): """Returns a rank-maximal matching of G, which is assumed to be a weighted bipartite graph, using Irving's algorithm. Args: G (nx.Graph): Weighted bipartite Graph with nodes named after natural numbers and positive weights on each edge. Agents are assumed to be nodes 1 through i for some i <= n. agent_cap (int): The numerical label of the last agent; that is, if agents are enumerated by nodes 1 through i, then agent_cap is equal to i. Defaults to len(G.nodes)//2 if not given. Returns: A set of 2-tuples representing a matching on G that has the rank-maximality property. """ if agent_cap is None: agent_cap = len(G.nodes) // 2 H = G.copy() n = len(H.nodes) rankify_graph(H, agent_cap) edge_list = [set() for i in range(n)] for (agent, good) in H.edges: edge_list[H[agent][good]['rank']].add((agent, good)) I = nx.Graph() I.add_nodes_from(H.nodes) S = set() for i in range(n): I.add_edges_from(edge_list[i]) S = nx.maximal_matching(I) even_odd_unreachable_decomposition(I) for j in range(i + 1, n): to_remove = set() for (u, v) in edge_list[j]: if I.nodes[u]['decomp'] in [ 'O', 'U' ] or I.nodes[v]['decomp'] in ['O', 'U']: to_remove.add((u, v)) edge_list[j] = edge_list[j].difference(to_remove) for (x, y) in I.edges: if I.nodes[x]['decomp'] + I.nodes[y]['decomp'] in [ 'OO', 'UO', 'OU' ]: I.remove_edge((x, y)) return S
def bottleneckassignment(Bottleneckgraph): """ :param Bottleneckgraph: networkx graph between initial states of the agent and initial elements of the targets :return: matching: optimal bottleneck matching between agents and assignments """ costlow=0 costhigh=1e6 #compute optimal bottleneck matching print("computing bottleneck assignment") while costhigh-costlow>1e-3: aux_graph=Bottleneckgraph.copy() cost_bisec=(costhigh+costlow)/2 #remove edges if the cost is larger than the current cost dict_item=list(aux_graph.edges(data=True)) for item in dict_item: if aux_graph[item[0]][item[1]]['weight']>cost_bisec: aux_graph.remove_edge(item[0],item[1]) #print(aux_graph.edges) #for item in aux_graph.edges: # print(item,aux_graph[item[0]][item[1]]['weight']) #try if there exists a matching, if not, do not return it matching = nx.maximal_matching(aux_graph) matching_node=[] for item in list(matching): matching_node.append(item[0]) matching_node.append(item[1]) matchflag=True for nodes in aux_graph: #print(nodes,matching,list(matching),nodes in matching_node,matching_node) if nodes in matching_node: pass else: matchflag=False if matchflag: #matching=nx.maximal_matching(aux_graph) costhigh=cost_bisec #print(matching,cost_bisec,"matching") matchingdict=dict() for item in list(matching): matchingdict[item[0]]=item[1] matchingdict[item[1]]=item[0] else: costlow=cost_bisec return matchingdict
def maximal_matching(nombre):#Para Grafo Simple Aciclico No dirigido df = pd.read_csv(nombre, header=None) b = nx.from_pandas_adjacency(df, create_using=nx.Graph()) for i in range(30): inicio = datetime.datetime.now() for key in range(50): # Ejecutar las 50 corridas nx.maximal_matching(b) final = datetime.datetime.now() tiempos.append((final - inicio).total_seconds()) # Guardo los tiempos de las corridas media=np.mean(tiempos) desv=np.std(tiempos) mediana=np.median(tiempos) nodos=nx.number_of_nodes(b) arcos=nx.number_of_edges(b) salvar=[] salvar.append(media) salvar.append(desv) salvar.append(mediana) salvar.append(nodos) salvar.append(arcos) return salvar
def test_maximal_matching(): graph = nx.Graph() graph.add_edge(0, 1) graph.add_edge(0, 2) graph.add_edge(0, 3) graph.add_edge(0, 4) graph.add_edge(0, 5) graph.add_edge(1, 2) matching = nx.maximal_matching(graph) vset = set(u for u, v in matching) vset = vset | set(v for u, v in matching) for edge in graph.edges_iter(): u, v = edge ok_(len(set([v]) & vset) > 0 or len(set([u]) & vset) > 0, \ "not a proper matching!") eq_(1, len(matching), "matching not length 1!") graph = nx.Graph() graph.add_edge(1, 2) graph.add_edge(1, 5) graph.add_edge(2, 3) graph.add_edge(2, 5) graph.add_edge(3, 4) graph.add_edge(3, 6) graph.add_edge(5, 6) matching = nx.maximal_matching(graph) vset = set(u for u, v in matching) vset = vset | set(v for u, v in matching) for edge in graph.edges_iter(): u, v = edge ok_(len(set([v]) & vset) > 0 or len(set([u]) & vset) > 0, \ "not a proper matching!")
def min_edge_dominating_set(graph): """Return minimum weight dominating edge set. Parameters ---------- graph : NetworkX graph Undirected graph Returns ------- min_edge_dominating_set : set Returns a set of dominating edges whose size is no more than 2 * OPT. """ if not graph: raise ValueError("Expected non-empty NetworkX graph!") return nx.maximal_matching(graph)
def mwm_homs(homs, ls, rs): '''get max cardinamlity homs''' edgelist = [] for l, r in homs: if l in ls and r in rs: edgelist.append((l, r)) G = nx.from_edgelist(edgelist) _hs = nx.maximal_matching(G) hs = [] for pair in _hs: if pair[0] in rs and pair[1] in ls: hs.append((pair[1], pair[0])) elif pair[1] in rs and pair[0] in ls: hs.append(pair) else: assert False, "We shouldn't have this case..." return hs
def contract_edges_matching(G, num_iters=2): """Given a graph G and a desired number of edges to be contracted, contracts edges uniformly at random (non-mutating of the original graph). Edges are contracted such that the two endpoints are now "identified" with one another. This mapping is returned as a dictionary If more edges are provided than can be contracted, an error is thrown. Returns (1) contracted graph (NetworkX Graph); (2) identified nodes dictionary (NetworkX node -> NetworkX node) """ identified_nodes = {} for _ in range(num_iters): edges = list(G.edges) matching = nx.maximal_matching(G) for vertex_pair in matching: identified_nodes[vertex_pair[0]] = vertex_pair[ 0] # right gets contracted into left G = nx.contracted_edge(G, vertex_pair, self_loops=False) return G, identified_nodes
def execute_all_possible_int_gates(routing: Routing, int_pairs: Set[frozenset]) -> bool: int_graph = nx.Graph() gate_executed = False for int_pair in int_pairs: hard_qb0 = routing.mapping.log2hard[list(int_pair)[0]] hard_qb1 = routing.mapping.log2hard[list(int_pair)[1]] if routing.qpu.graph.has_edge(hard_qb0, hard_qb1): if routing.layers[-1].int_gate_applicable(frozenset((hard_qb0, hard_qb1))): int_graph.add_edge(hard_qb1, hard_qb0) gate_executed = True matching = nx.maximal_matching(int_graph) for match in matching: gate = frozenset(match) log_qb0 = routing.mapping.hard2log[list(match)[0]] log_qb1 = routing.mapping.hard2log[list(match)[1]] int_pair = frozenset((log_qb0, log_qb1)) routing.apply_int(gate) int_pairs.remove(int_pair) return gate_executed
def draw_bipartite_matching(ax): BasicGraphSet.ax_set(ax, 'maximal matching') g = nx.Graph() g.add_edges_from([('a', 'b'), ('a', 'c'), ('a', 'e'), ('b', 'd'), ('d', 'e')]) if not nx.bipartite.is_bipartite(g): print('This graph is not bipartite') return print('This graph is bipartite') l, r = nx.bipartite.sets(g) node_colors = BasicGraphSet.set_property_for_nodes(g.nodes, l, 'green', 'yellow') max_matching = nx.maximal_matching(g) # a dict, eg {('a', 'b'), ('b', 'c)} edge_colors = BasicGraphSet.set_property_for_edges(g.edges, max_matching, 'black', 'r') BasicGraphSet.basic_draw_color(g, ax, edge_colors=edge_colors, node_colors=node_colors)
def max_cardinality_matching(Mrkt, Agents, verbose=False): """ Find a maximal cardinality matching in the graph. A matching is a subset of edges in which no node occurs more than once. The cardinality of a matching is the number of matched edges. Implemented by NetworkX Runtime: O(e) for e edges The algorithm greedily selects a maximal matching M of the graph G (i.e. no superset of M exists). It runs in `O(|E|)` time. Arguments --------- Mrkt: mm.Market object The market in which the matches are made Agents: list list of agents initiating matches verbose: bool Whether algorithm prints information on action Returns ------- dict { agent.name : agent.name } of matches """ if verbose: print("\nMax Weight Match Algorithm\n") print("Agents to match ", [a.name for a in Agents], "\n") # If Agents not whole market, get subgraph if len(Mrkt.Graph.nodes()) != len(Agents): to_match = deepcopy(Mrkt.Graph.subgraph(Agents)) else: to_match = Mrkt.Graph # Workaround of assertionerror in Nx verifyOptimum() function # Breaks around integer weights for u, v, d in to_match.edges(data=True): d['weight'] = float(d['weight']) mate = nx.maximal_matching(to_match) result = {a[0].name: a[1].name for a in mate} return result
def Dilworth(ng): global unmatched g = nx.Graph() gdas = nx.Graph() # Creating bipirate graph from a partial order, and partitioning into chains according to a matching for n in nx.topological_sort(ng, ng.nodes()): g.add_node(Copy0(n)) g.node[Copy0(n)]['label'] = Copy0(ng.node[n]['label']) g.add_node(Copy1(n)) g.node[Copy1(n)]['label'] = Copy1(ng.node[n]['label']) gdas.add_node(Copy0(n)) gdas.add_node(Copy1(n)) for n in nx.nodes(ng): for (u, v) in nx.edges(ng, n): g.add_edge(Copy0(n), Copy1(v)) # Running matching algorithm s = nx.maximal_matching(g) gdas.add_edges_from(s) unmatched = nx.number_of_nodes(ng) # print 'unmatched = ', unmatched # nx.drawing.nx_pydot.write_dot(gdas,'sample.dot') # print s chains = [] while len(s) > 0: # print '********', len(s) seed = next(iter(s)) chain = [] ExtendForward(gdas, ng, s, seed, chain, chains) # print '///////////' ExtendBackward(gdas, ng, s, seed, chain, chains) # print len(s) # print len(chain) + 1 unmatched = unmatched - 1 chains.append(chain)
def min_maximal_matching(graph): """Returns a set of edges such that no two edges share a common endpoint and every edge not in the set shares some common endpoint in the set. Parameters ---------- graph : NetworkX graph Undirected graph Returns ------- min_maximal_matching : set Returns a set of edges such that no two edges share a common endpoint and every edge not in the set shares some common endpoint in the set. Cardinality will be 2*OPT in the worst case. References ---------- .. [1] Vazirani, Vijay Approximation Algorithms (2001) """ return nx.maximal_matching(graph)
def displayMatching(people: dict, edges: List[list]): graph = nx.Graph() for p in people.values(): graph.add_node(p.p_id) for edge in edges: w = edge[0].rel + edge[1].rel graph.add_edge(edge[0].p_id, edge[1].p_id, weight=w) max_match = nx.maximal_matching(graph) max_match_w = nx.max_weight_matching(graph) labels = nx.get_edge_attributes(graph, 'weight') plt.ion() plt.figure() plt.title("Max Matching Graph") pos = nx.spring_layout(graph, seed=42) pos2 = nx.spring_layout(graph, seed=42) nx.draw(graph, pos=pos, with_labels=True, font_color='w') nx.draw_networkx_edges(graph, pos=pos, edgelist=max_match, edge_color='r', width=4) nx.draw_networkx_edge_labels(graph, pos, edge_labels=labels) plt.figure() plt.title("Relative Graph") nx.draw(graph, pos=pos2, with_labels=True, font_color='w') nx.draw_networkx_edges( graph, pos=pos2, edgelist=max_match_w, edge_color='g', width=4, ) nx.draw_networkx_edge_labels(graph, pos2, edge_labels=labels) plt.ioff() plt.show()
def min_edge_dominating_set(G): r"""Return minimum cardinality edge dominating set. Parameters ---------- G : NetworkX graph Undirected graph Returns ------- min_edge_dominating_set : set Returns a set of dominating edges whose size is no more than 2 * OPT. Notes ----- The algorithm computes an approximate solution to the edge dominating set problem. The result is no more than 2 * OPT in terms of size of the set. Runtime of the algorithm is `O(|E|)`. """ if not G: raise ValueError("Expected non-empty NetworkX graph!") return nx.maximal_matching(G)
def min_edge_dominating_set(G): """Return minimum cardinality edge dominating set. Parameters ---------- G : NetworkX graph Undirected graph Returns ------- min_edge_dominating_set : set Returns a set of dominating edges whose size is no more than 2 * OPT. Notes ----- The algorithm computes an approximate solution to the edge dominating set problem. The result is no more than 2 * OPT in terms of size of the set. Runtime of the algorithm is O(|E|). """ if not G: raise ValueError("Expected non-empty NetworkX graph!") return nx.maximal_matching(G)
def init(n): G = nx.Graph() G.add_nodes_from(range(1, n + 1)) # Le nombre d'arêtes max est de (n*(n-1))/2 et on cherche un remplissage de 0.25% nbAretesMax = (n * (n - 1)) / 2 remplissageSouhaitee = 0.25 * nbAretesMax while (G.number_of_edges() < remplissageSouhaitee ): #Remplissage est inférieur à 25% on ajoute des arêtes noeud1 = randint(1, n) noeud2 = noeud1 while ( noeud1 == noeud2 ): #Ici on ne veut pas qu'un graphe possède une arête pointant vers lui même. noeud2 = randint(1, n) G.add_edge(noeud1, noeud2) print("Le graphe possède les arêtes suivantes :") print(list(G.edges())) #print(list(G.nodes())) print("Affichage les couples de sommets permettant un maximum matching") print(nx.maximal_matching(G)) #Vérifier que on obtient bien : #Calcul de la solution optimale de VertexCover (recherche exhaustive) grapheParent = cp.deepcopy( G ) #Copie en profondeur de G (chaque modification de graphe2 ne modifiera pas G) #Ici on fait une boucle qui va vérifier que les différents graphes sont des VC. A la fin de la boucle, nous avons forcément trouvé min VC for i in range(1, n + 1): newpid = os.fork() if newpid == 0: #Si c'est un enfant grapheEnfant = cp.deepcopy(grapheParent) #print(isVertexCover(grapheParent,grapheEnfant)) print("Enfant: %d\n" % i) else: newpid = os.fork() pids = (os.getpid(), newpid)
def subtree_isomorphism(G, H): # Run the algorithm r = G.nodes()[0] # Enumerate all leaves in G by BFS leaves, children = find_leaves(G, r) print "Leaves:", leaves print "Children:", children # Initialize the S map S = {} for u in H.nodes(): for v in G.nodes(): S[(v,u)] = set() # Initialize S[] based on the leaves of G to start for gl in leaves: for u in H.nodes(): hleaves, dummyChildren = find_leaves(H, u) for hl in hleaves: S[(gl, hl)] = H.neighbors(u) ### CORRECT TO HERE # Main loop internals = find_internals(G, r, leaves) for i,v in enumerate(internals): childs = children[v] t = len(childs) hdegrees = find_nodes_of_at_most_degree(H, t + 1) for j,u in enumerate(hdegrees): uneighbors = H.neighbors(u) # u1,...,us s = len(uneighbors) X = uneighbors Y = childs edgeSet = [] for uu in X: for vv in Y: if (vv,uu) in S: if u in S[(vv, uu)]: edgeSet.append((uu, vv)) # Construct the bipartite graph between the two vertex sets bg = nx.Graph() bg.add_nodes_from(X, bipartite=0) bg.add_nodes_from(Y, bipartite=1) bg.add_edges_from(edgeSet) #pause(locals()) # Try to find all the maximal matchings for all i = 0..s mi_vector = [] m_star = 0 X_star = [] for si in range(-1, s): # Define X_0 = X and X_i = X \ {u_i} X_i = X # only if i = 0 (si == -1) u_i = u # fixed. if si >= 0: u_i = X[si] # X = uneighbors X_i = [uu for uu in X if uu != u_i] testGraph = nx.Graph() testGraph.add_nodes_from(X_i, bipartite=0) testGraph.add_nodes_from(Y, bipartite=1) edgeSet = [] for uu in X_i: neighbors = bg.neighbors(uu) for n in neighbors: edgeSet.append((uu, n)) testGraph.add_edges_from(edgeSet) m_i = len(nx.maximal_matching(testGraph)) mi_vector.append((m_i, u_i, X_i)) # record the X_i, this can be skipped #pause(locals()) if m_i > m_star: m_star = m_i X_star = X_i if (v,u) not in S: S[(v,u)] = set() for (m_i, u_i, X_i) in mi_vector: if m_i == len(X_i): #m_star: S[(v, u)].add(u_i) if u in S[(v, u)]: print v, u return "YES" return "NO"
def twoOptApprox(graph): max_matching = list(nx.maximal_matching(graph)) res = [x[0] for x in max_matching] res.extend([x[1] for x in max_matching]) return res
if (g_person_node_count+g_wine_node_count) < MIN_MEM_NODE_COUNT: print "Merge Tree Overlaps" pt.merge_overlaps() wt.merge_overlaps() print "Buffering..." while (g_person_node_count+g_wine_node_count) < MAX_MEM_NODE_COUNT and more_file: line = f.readline() #read in line from input if line: if add_line_to_graph(line): nodes_to_process = True else: more_file = False print "Buffering Done" print "FG Length:",len(fg) max_match = nx.maximal_matching(fg) print "Match Count:",len(max_match) if len(max_match) == 0: fg.clear() g_person_node_count = 0 g_wine_node_count = 0 nodes_to_process = False for node in max_match: if node[0][0] == "w": wine = node[0] person = node[1] elif node[0][0] == "p": person = node[0] wine = node[1] person_id = long(person.replace("p",""))
def test_valid_matching(self): edges = [(1, 2), (1, 5), (2, 3), (2, 5), (3, 4), (3, 6), (5, 6)] G = nx.Graph(edges) matching = nx.maximal_matching(G) assert_true(nx.is_maximal_matching(G, matching))
def train_val_test_split_adjacency(A, p_val=0.10, p_test=0.05, seed=0, neg_mul=1, every_node=True, connected=False, undirected=False, use_edge_cover=True, set_ops=True, asserts=False): """ Split the edges of the adjacency matrix into train, validation and test edges and randomly samples equal amount of validation and test non-edges. Parameters ---------- A : scipy.sparse.spmatrix Sparse unweighted adjacency matrix p_val : float Percentage of validation edges. Default p_val=0.10 p_test : float Percentage of test edges. Default p_test=0.05 seed : int Seed for numpy.random. Default seed=0 neg_mul : int What multiplicity of negative samples (non-edges) to have in the test/validation set w.r.t the number of edges, i.e. len(non-edges) = L * len(edges). Default neg_mul=1 every_node : bool Make sure each node appears at least once in the train set. Default every_node=True connected : bool Make sure the training graph is still connected after the split undirected : bool Whether to make the split undirected, that is if (i, j) is in val/test set then (j, i) is there as well. Default undirected=False use_edge_cover: bool Whether to use (approximate) edge_cover to find the minimum set of edges that cover every node. Only active when every_node=True. Default use_edge_cover=True set_ops : bool Whether to use set operations to construction the test zeros. Default setwise_zeros=True Otherwise use a while loop. asserts : bool Unit test like checks. Default asserts=False Returns ------- train_ones : array-like, shape [n_train, 2] Indices of the train edges val_ones : array-like, shape [n_val, 2] Indices of the validation edges val_zeros : array-like, shape [n_val, 2] Indices of the validation non-edges test_ones : array-like, shape [n_test, 2] Indices of the test edges test_zeros : array-like, shape [n_test, 2] Indices of the test non-edges """ assert p_val + p_test > 0 assert A.max() == 1 # no weights assert A.min() == 0 # no negative edges assert A.diagonal().sum() == 0 # no self-loops assert not np.any(A.sum(0).A1 + A.sum(1).A1 == 0) # no dangling nodes is_undirected = (A != A.T).nnz == 0 if undirected: assert is_undirected # make sure is directed A = sp.tril(A).tocsr() # consider only upper triangular A.eliminate_zeros() else: if is_undirected: warnings.warn('Graph appears to be undirected. Did you forgot to set undirected=True?') np.random.seed(seed) E = A.nnz N = A.shape[0] s_train = int(E * (1 - p_val - p_test)) idx = np.arange(N) # hold some edges so each node appears at least once if every_node: if connected: assert connected_components(A)[0] == 1 # make sure original graph is connected A_hold = minimum_spanning_tree(A) else: A.eliminate_zeros() # makes sure A.tolil().rows contains only indices of non-zero elements d = A.sum(1).A1 if use_edge_cover: hold_edges = np.array(list(nx.maximal_matching(nx.DiGraph(A)))) not_in_cover = np.array(list(set(range(N)).difference(hold_edges.flatten()))) # makes sure the training percentage is not smaller than N/E when every_node is set to True min_size = hold_edges.shape[0] + len(not_in_cover) if min_size > s_train: raise ValueError('Training percentage too low to guarantee every node. Min train size needed {:.2f}' .format(min_size / E)) d_nic = d[not_in_cover] hold_edges_d1 = np.column_stack((not_in_cover[d_nic > 0], np.row_stack(map(np.random.choice, A[not_in_cover[d_nic > 0]].tolil().rows)))) if np.any(d_nic == 0): hold_edges_d0 = np.column_stack((np.row_stack(map(np.random.choice, A[:, not_in_cover[d_nic == 0]].T.tolil().rows)), not_in_cover[d_nic == 0])) hold_edges = np.row_stack((hold_edges, hold_edges_d0, hold_edges_d1)) else: hold_edges = np.row_stack((hold_edges, hold_edges_d1)) else: # makes sure the training percentage is not smaller than N/E when every_node is set to True if N > s_train: raise ValueError('Training percentage too low to guarantee every node. Min train size needed {:.2f}' .format(N / E)) hold_edges_d1 = np.column_stack( (idx[d > 0], np.row_stack(map(np.random.choice, A[d > 0].tolil().rows)))) if np.any(d == 0): hold_edges_d0 = np.column_stack((np.row_stack(map(np.random.choice, A[:, d == 0].T.tolil().rows)), idx[d == 0])) hold_edges = np.row_stack((hold_edges_d0, hold_edges_d1)) else: hold_edges = hold_edges_d1 if asserts: assert np.all(A[hold_edges[:, 0], hold_edges[:, 1]]) assert len(np.unique(hold_edges.flatten())) == N A_hold = edges_to_sparse(hold_edges, N) A_hold[A_hold > 1] = 1 A_hold.eliminate_zeros() A_sample = A - A_hold s_train = s_train - A_hold.nnz else: A_sample = A idx_ones = np.random.permutation(A_sample.nnz) ones = np.column_stack(A_sample.nonzero()) train_ones = ones[idx_ones[:s_train]] test_ones = ones[idx_ones[s_train:]] # return back the held edges if every_node: train_ones = np.row_stack((train_ones, np.column_stack(A_hold.nonzero()))) n_test = len(test_ones) * neg_mul if set_ops: # generate slightly more completely random non-edge indices than needed and discard any that hit an edge # much faster compared a while loop # in the future: estimate the multiplicity (currently fixed 1.3/2.3) based on A_obs.nnz if undirected: random_sample = np.random.randint(0, N, [int(2.3 * n_test), 2]) random_sample = random_sample[random_sample[:, 0] > random_sample[:, 1]] else: random_sample = np.random.randint(0, N, [int(1.3 * n_test), 2]) random_sample = random_sample[random_sample[:, 0] != random_sample[:, 1]] test_zeros = random_sample[A[random_sample[:, 0], random_sample[:, 1]].A1 == 0] test_zeros = np.row_stack(test_zeros)[:n_test] assert test_zeros.shape[0] == n_test else: test_zeros = [] while len(test_zeros) < n_test: i, j = np.random.randint(0, N, 2) if A[i, j] == 0 and (not undirected or i > j) and (i, j) not in test_zeros: test_zeros.append((i, j)) test_zeros = np.array(test_zeros) # split the test set into validation and test set s_val_ones = int(len(test_ones) * p_val / (p_val + p_test)) s_val_zeros = int(len(test_zeros) * p_val / (p_val + p_test)) val_ones = test_ones[:s_val_ones] test_ones = test_ones[s_val_ones:] val_zeros = test_zeros[:s_val_zeros] test_zeros = test_zeros[s_val_zeros:] if undirected: # put (j, i) edges for every (i, j) edge in the respective sets and form back original A symmetrize = lambda x: np.row_stack((x, np.column_stack((x[:, 1], x[:, 0])))) train_ones = symmetrize(train_ones) val_ones = symmetrize(val_ones) val_zeros = symmetrize(val_zeros) test_ones = symmetrize(test_ones) test_zeros = symmetrize(test_zeros) A = A.maximum(A.T) if asserts: set_of_train_ones = set(map(tuple, train_ones)) assert train_ones.shape[0] + test_ones.shape[0] + val_ones.shape[0] == A.nnz assert (edges_to_sparse(np.row_stack((train_ones, test_ones, val_ones)), N) != A).nnz == 0 assert set_of_train_ones.intersection(set(map(tuple, test_ones))) == set() assert set_of_train_ones.intersection(set(map(tuple, val_ones))) == set() assert set_of_train_ones.intersection(set(map(tuple, test_zeros))) == set() assert set_of_train_ones.intersection(set(map(tuple, val_zeros))) == set() assert len(set(map(tuple, test_zeros))) == len(test_ones) * neg_mul assert len(set(map(tuple, val_zeros))) == len(val_ones) * neg_mul assert not connected or connected_components(A_hold)[0] == 1 assert not every_node or ((A_hold - A) > 0).sum() == 0 return train_ones, val_ones, val_zeros, test_ones, test_zeros
def matching(net): return setSize(nx.maximal_matching(net),net.number_of_edges(),'maximal_matching')
import random import matplotlib.pyplot as plt import numpy as np g=nx.random_graphs.binomial_graph(1000, 0.01) p1=0.1#bad match p2=0.5#back to market paces=range(10,1010,10) ans={i:[]for i in paces} for k in range(50): print k for pace in paces: pos=pace cur=[i for i in g.nodes() if i<pos] bad=0 while True: match=nx.maximal_matching(g.subgraph(cur)) for i in match: for j in i: if random.random()>p1: cur.remove(j) continue if random.random()>p2: bad+=1 cur.remove(j) cur+=range(pos,1000) if pos>=1000: break pos=pos+1000 bad+=len([i for i in cur if i<1000]) ans[pace]+=[bad] plt.plot(paces,[np.mean(ans[i]) for i in paces])
def main(): """The main function.""" for edge_list in generate_edges(): print(nx.maximal_matching(nx.Graph(edge_list)))
def checkPolar_all(atom_coor,atomLabels, vecX, vecY, z_digit=4, dist_tol_rate=0.01, max_compare = float("Inf"), inverse_struc = False): # Description of the input variables: # - atom_coor: of the atoms, numpy.array(Natoms,3) # - atomLabels: numpy.array with integers denoting atom types, # i.e [0,1,1,0,2,...,natoms]. The order of the atoms is the same # as in positions array. # - atomTypes: dictionary that allows to decode entries in the atomLabels # in terms of real chemical species. # Example: # atomTypes = {0: 'Ga', 1: 'As', 2: 'H'} # which means that integer 0 corresponds to "Ga", integer 1 to "As" and 2 to "H" # Usage: # find what is the atom type of the 3rd atom in the structure: # atomLabels = [0,1,1,0,2] # atom = atomLabels[2] # remeberin Python we count from 0, so 3rd atom is 2nd in the structure # type = atomTypes[atom] # In this case atom will be set to "1", and type to "As" # # - vec_x: lattice vector X, numpy.array[x1, x2, x3] # - vec_y: lattice vector Y, numpy.array[y1, y2, y3] # first 180 primes primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069]; nAtoms = len(atomLabels); # represent the atom types by prime numbers ele_n = np.empty([nAtoms, 1]); ii=0; atomLabels = np.array(atomLabels); for i in xrange(min(atomLabels), max(atomLabels)+1): ele_n[atomLabels == i]= primes[ii]; ii += 1; ele_n = np.outer(ele_n,ele_n); ele_n[range(nAtoms), range(nAtoms)] = 0; # build the distance matrix (size nAtoms*nAtoms, entry i,j represent for the distance between i-th atom and j-th atom) atom_dist = np.empty([nAtoms, nAtoms], dtype=float); for i in xrange(0, nAtoms): for j in xrange(i,nAtoms): atom_dist[i,j] = compute_min_dist(atom_coor[i, 0:2] - atom_coor[j, 0:2], vecX, vecY); atom_dist[i,j] = atom_dist[i,j]+(atom_coor[i, 2] - atom_coor[j, 2])**2; atom_dist[j,i] = atom_dist[i,j] atom_dist[range(nAtoms), range(nAtoms)] = -1; # avoid zero-division in later steps # round the z-coordinate atom_coor[:, 2] = np.around(atom_coor[:, 2], decimals = z_digit); # atoms with same cut_z coord are considered on the same "surface" # inverse_struc=False: the resut is ordered from small to large if inverse_struc: surface_z= np.squeeze(np.unique(atom_coor[:, 2], return_inverse=True))[0]; else: surface_z= np.squeeze(np.unique(atom_coor[:, 2], return_inverse=False)); surface_n=len(surface_z); # number of surfaces surface_thickness = surface_n; init_z = surface_z[-1]; # the first surface to consider firstRound = False; forDelete = np.zeros([nAtoms], dtype=bool); is_Polar = np.zeros([surface_n], dtype=bool); z_coords = surface_z; minDiffRate = np.empty([surface_n]) typeDiff = np.zeros([surface_n], dtype=bool); for current_surface in xrange(surface_thickness-1): if max_compare> (surface_n/2): # take advange of integer division max_compare=(surface_n/2); for nSurface in xrange(0,max_compare): #each row represents for an atom # the indices of atoms on the upper surface & lower surface u_lidx = atom_coor[:, 2]==surface_z[nSurface]; l_lidx =atom_coor[:, 2]==surface_z[-nSurface-1]; # if the number of atoms are differnent if sum(u_lidx) != sum(l_lidx): is_Polar[current_surface]=True; break; nAtomPerLayer = sum(u_lidx); data_upper_dist= atom_dist[u_lidx,:]; data_lower_dist= atom_dist[l_lidx,:]; # # can speed up the code if we only want to get polar/non-polar # if np.setdiff1d(data_upper_dist,data_lower_dist): # polar = True; # break; data_upper_type= ele_n[u_lidx,:]; data_lower_type= ele_n[l_lidx,:]; # # can speed up the code if we only want to get polar/non-polar # if np.setdiff1d(data_upper_type, data_lower_type).size: # polar = True; # break; # for each atom, sort the distance from this atom to the others (small to large) sort1idx_u = np.argsort(data_upper_dist, axis = 1); sort1idx_l = np.argsort(data_lower_dist,axis = 1); for i in xrange(nAtomPerLayer): data_upper_type[i,:] = data_upper_type[i,sort1idx_u[i,:]]; data_lower_type[i,:] = data_lower_type[i,sort1idx_l[i,:]]; data_upper_dist[i,:] = data_upper_dist[i,sort1idx_u[i,:]]; data_lower_dist[i,:] = data_lower_dist[i,sort1idx_l[i,:]]; # for each atom, sort the type from this atom to the others (small to large) sort2idx_u = np.argsort(data_upper_type, axis = 1); sort2idx_l = np.argsort(data_lower_type,axis = 1); for i in xrange(nAtomPerLayer): data_upper_type[i,:] = data_upper_type[i,sort2idx_u[i,:]]; data_lower_type[i,:] = data_lower_type[i,sort2idx_l[i,:]]; data_upper_dist[i,:] = data_upper_dist[i,sort2idx_u[i,:]]; data_lower_dist[i,:] = data_lower_dist[i,sort2idx_l[i,:]]; dist_diff = np.zeros([nAtomPerLayer,nAtomPerLayer], dtype = float); # rate of difference on distance type_ok = np.zeros([nAtomPerLayer,nAtomPerLayer], dtype = bool); # true if the type items are matching between a upper-atom and a lower-atom for idx_upper in xrange(nAtomPerLayer): for idx_lower in xrange(nAtomPerLayer): dist_diff[idx_upper,idx_lower] = max(abs(np.divide(data_upper_dist[idx_upper,:]-data_lower_dist[idx_lower,:], data_upper_dist[idx_upper,:]+data_lower_dist[idx_lower,:]))); type_ok[idx_upper,idx_lower]= all(data_upper_type[idx_upper,:]==data_lower_type[idx_lower,:]); match_matrix = (dist_diff<=dist_tol_rate) & type_ok; g = networkx.to_networkx_graph(match_matrix); # # find the maximal matching of graph g if len(networkx.maximal_matching(g))< nAtomPerLayer: is_Polar[current_surface]=True; g = networkx.to_networkx_graph(type_ok); if len(networkx.maximal_matching(g))< nAtomPerLayer: typeDiff[current_surface] = True; minDiffRate[current_surface] = float("nan"); else: minDiffRate[current_surface] = np.min([np.min(dist_diff), minDiffRate[current_surface]]); break; else: minDiffRate[current_surface] = float("nan"); # END of nSurface loop data_delete = (atom_coor[:, 2]==surface_z[-1]); atom_dist = atom_dist[~data_delete,:]; atom_dist = atom_dist[:,~data_delete]; ele_n = ele_n[~data_delete,:]; ele_n = ele_n[:,~data_delete]; atom_coor = atom_coor[~data_delete,:]; surface_n=surface_n-1; surface_z = np.delete(surface_z, -1); minDiffRate[-1] = float("nan") is_Polar = is_Polar[::-1]; minDiffRate = minDiffRate[::-1] typeDiff = typeDiff[::-1] return is_Polar, z_coords, minDiffRate, typeDiff
def get_driver_nodes(DG): '''Return the driver nodes number and driver nodes from a DiGraph DG Basic Idea: Given a graph DG, create a new undirected bipartite graph, BG suppose DG has n nodes, the the BG has 2*n nodes, the first n nodes [0, n) form the left parts of BG, the [n, 2*n) nodes form the right part of BG, for each edge form DG, say, 1-->3, add edges in BG 1---(3+n) then call the maximum matching algorithm find the matched nodes All the unmatched nodes are the driver nodes we are looking for Parameters ---------- DG: networkx.DiGraph, directed graph, node number start from 0 Returns ------- driver node num: the number of driver nodes driver nodes: the driver nodes we are looking for Notes: ------- The index of nodes in DG must start from 0, 1, 2, 3... References: ----------- [1] Yang-Yu Liu, Jean-Jacques Slotine, Albert L. Barabasi. Controllability of complex networks. Nature, 2011. ''' assert(nx.is_directed(DG)) nodeNum = DG.number_of_nodes() edgeNum = DG.number_of_edges() # convert to a bipartite graph G = nx.Graph() left_nodes = ['a'+str(node) for node in G.nodes()] right_nodes = ['b'+str(node) for node in G.nodes()] G.add_nodes_from(left_nodes) G.add_nodes_from(right_nodes) for edge in DG.edges(): da = 'a' + str(edge[0]) db = 'b' + str(edge[1]) G.add_edge(da, db) assert(nx.is_bipartite(G)) # maximum matching algorithm matched_edges = nx.maximal_matching(G) # find all the matched and unmatched nodes matched_nodes = [int(edge[0][1:]) if edge[0][0] == 'b' else int(edge[1][1:]) for edge in matched_edges] unmatched_nodes = [node for node in DG.nodes() if node not in matched_nodes] unmatched_nodes_num = len(unmatched_nodes) # perfect matching isPerfect = False if unmatched_nodes_num == 0: print '>>> Perfect Match Found ! <<<' isPerfect = True unmatched_nodes_num = 1 unmatched_nodes = [0] return (isPerfect, unmatched_nodes_num, unmatched_nodes)
def checkPolar(atom_coor,atomLabels, vecX, vecY, z_digit=4, dist_tol_rate=0.01, max_compare = float("Inf"), inverse_struc = False): # Description of the input variables: # - atom_coor: of the atoms, numpy.array(Natoms,3) # - atomLabels: numpy.array with integers denoting atom types, # i.e [0,1,1,0,2,...,natoms]. The order of the atoms is the same # as in positions array. # - atomTypes: dictionary that allows to decode entries in the atomLabels # in terms of real chemical species. # Example: # atomTypes = {0: 'Ga', 1: 'As', 2: 'H'} # which means that integer 0 corresponds to "Ga", integer 1 to "As" and 2 to "H" # Usage: # find what is the atom type of the 3rd atom in the structure: # atomLabels = [0,1,1,0,2] # atom = atomLabels[2] # remeberin Python we count from 0, so 3rd atom is 2nd in the structure # type = atomTypes[atom] # In this case atom will be set to "1", and type to "As" # # - vec_x: lattice vector X, numpy.array[x1, x2, x3] # - vec_y: lattice vector Y, numpy.array[y1, y2, y3] # Return values are # polar = {True,False} - is structure polar or not # periodicity = 0 - double number saying what is the periodicity of the structure in angstrom # minDiffRate - double number saying what is the minimal distance rate found during the checking procedure (especially useful for understanding the polar structures) periodicity = float("nan") # first 180 primes primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069]; nAtoms = len(atomLabels); # represent the atom types by prime numbers ele_n = np.empty([nAtoms, 1]); ii=0; atomLabels = np.array(atomLabels); for i in xrange(min(atomLabels), max(atomLabels)+1): ele_n[atomLabels == i]= primes[ii]; ii += 1; ele_n = np.outer(ele_n,ele_n); ele_n[range(nAtoms), range(nAtoms)] = 0; # build the distance matrix (size nAtoms*nAtoms, entry i,j represent for the distance between i-th atom and j-th atom) atom_dist = np.empty([nAtoms, nAtoms], dtype=float); for i in xrange(0, nAtoms): for j in xrange(i,nAtoms): atom_dist[i,j] = compute_min_dist(atom_coor[i, 0:2] - atom_coor[j, 0:2], vecX, vecY); atom_dist[i,j] = atom_dist[i,j]+(atom_coor[i, 2] - atom_coor[j, 2])**2; atom_dist[j,i] = atom_dist[i,j] atom_dist[range(nAtoms), range(nAtoms)] = -1; # avoid zero-division in later steps # round the z-coordinate atom_coor[:, 2] = np.around(atom_coor[:, 2], decimals = z_digit); # atoms with same cut_z coord are considered on the same "surface" # inverse_struc=False: the resut is ordered from small to large if inverse_struc: surface_z= np.squeeze(np.unique(atom_coor[:, 2], return_inverse=True))[0]; else: surface_z= np.squeeze(np.unique(atom_coor[:, 2], return_inverse=False)); surface_n=len(surface_z); # number of surfaces init_z = surface_z[-1]; # the first surface to consider firstRound = False; forDelete = np.zeros([nAtoms], dtype=bool); while(surface_n>=2 and not(abs(surface_z[0]-surface_z[-1])<abs(init_z-surface_z[-1]) and not(firstRound))): # the first round non-polar must be found within the upper half of the structure if max_compare> (surface_n/2): # take advange of integer division max_compare=(surface_n/2); polar=False; doCompare = True; minDiffRate = 1 typeDiff = False if firstRound: if abs(init_z-surface_z[-1]) < perodicity_lower_bound: doCompare = False; if doCompare: for nSurface in xrange(0,max_compare): #each row represents for an atom # the indices of atoms on the upper surface & lower surface u_lidx = atom_coor[:, 2]==surface_z[nSurface]; u_lidx = u_lidx [~forDelete]; l_lidx =atom_coor[:, 2]==surface_z[-nSurface-1]; l_lidx = l_lidx[~forDelete]; # if the number of atoms are different if sum(u_lidx) != sum(l_lidx): polar=True; break; nAtomPerLayer = sum(u_lidx); data_upper_dist= atom_dist[u_lidx,:]; data_lower_dist= atom_dist[l_lidx,:]; # # can speed up the code if we only want to get polar/non-polar # if np.setdiff1d(data_upper_dist,data_lower_dist): # polar = True; # break; data_upper_type= ele_n[u_lidx,:]; data_lower_type= ele_n[l_lidx,:]; # # can speed up the code if we only want to get polar/non-polar # if np.setdiff1d(data_upper_type, data_lower_type).size: # polar = True; # break; # for each atom, sort the distance from this atom to the others (small to large) sort1idx_u = np.argsort(data_upper_dist, axis = 1); sort1idx_l = np.argsort(data_lower_dist,axis = 1); for i in xrange(nAtomPerLayer): data_upper_type[i,:] = data_upper_type[i,sort1idx_u[i,:]]; data_lower_type[i,:] = data_lower_type[i,sort1idx_l[i,:]]; data_upper_dist[i,:] = data_upper_dist[i,sort1idx_u[i,:]]; data_lower_dist[i,:] = data_lower_dist[i,sort1idx_l[i,:]]; # for each atom, sort the type from this atom to the others (small to large) sort2idx_u = np.argsort(data_upper_type, axis = 1); sort2idx_l = np.argsort(data_lower_type,axis = 1); for i in xrange(nAtomPerLayer): data_upper_type[i,:] = data_upper_type[i,sort2idx_u[i,:]]; data_lower_type[i,:] = data_lower_type[i,sort2idx_l[i,:]]; data_upper_dist[i,:] = data_upper_dist[i,sort2idx_u[i,:]]; data_lower_dist[i,:] = data_lower_dist[i,sort2idx_l[i,:]]; dist_diff = np.zeros([nAtomPerLayer*2,nAtomPerLayer*2], dtype = float); # rate of difference on distance type_ok = np.zeros([nAtomPerLayer*2,nAtomPerLayer*2], dtype = bool); # true if the type items are matching between a upper-atom and a lower-atom for idx_upper in xrange(nAtomPerLayer): for idx_lower in xrange(nAtomPerLayer): dist_diff[idx_upper,nAtomPerLayer+idx_lower] = max(abs(np.divide(data_upper_dist[idx_upper,:]-data_lower_dist[idx_lower,:], data_upper_dist[idx_upper,:]+data_lower_dist[idx_lower,:]))); type_ok[idx_upper,nAtomPerLayer+idx_lower]= all(data_upper_type[idx_upper,:]==data_lower_type[idx_lower,:]); dist_diff = dist_diff + np.transpose(dist_diff); type_ok = type_ok + np.transpose(type_ok); match_matrix = (dist_diff<=dist_tol_rate) & type_ok; g = networkx.to_networkx_graph(match_matrix); # find the maximal matching of graph g if len(networkx.maximal_matching(g))< nAtomPerLayer: polar=True; g = networkx.to_networkx_graph(type_ok); if len(networkx.maximal_matching(g))< nAtomPerLayer: typeDiff = True; minDiffRate = float("nan"); else: minDiffRate = np.min([np.min(dist_diff), minDiffRate]); break; # END of nSurface loop if not(polar) and not(firstRound): # first round NonPolar firstRound = True layer_thickness = 0 minNP_z = np.array([surface_z[-1]]) perodicity_lower_bound = abs(init_z - minNP_z); # the periodicity should be larger than this else: if not(polar) and firstRound and (abs(minNP_z[0] - surface_z[-1])>perodicity_lower_bound): # the second round non-polar minNP_z = np.append(minNP_z, surface_z[-1]); layer_thickness = layer_thickness + 1; z_thickness = minNP_z[0]-minNP_z[-1]; minDiffRate = float("nan") # vz(3) = z_thickness; # isNP = ismember(atom_coor(:,3), minNP_z); # minNPStruc= atom_coor(isNP,:); # minNPStruc(:,3)= minNPStruc(:,3) - minNP_z(end); # atom_type = atom_type(isNP); # atom_cell=[num2cell(minNPStruc) atom_type]; # # create a new txt file that contains the maximal non-polar structure # isWin = ~isempty(strfind(computer, 'PCWIN')); # [pathstr,name,ext] = fileparts(filepath); # mkdir(pathstr,'minNonPolar5'); # if isWin # pathstr=strcat(pathstr, '\minNonPolar5'); # else # pathstr=strcat(pathstr, '/minNonPolar5'); # end # oldpath=cd(pathstr); # fileID=fopen([name '-minNonPolar5' ext], 'w+'); # formatSpec1='lattice_vector \t %f \t %f \t %f \n'; # fprintf(fileID,formatSpec1,vx); # fprintf(fileID,formatSpec1,vy); # fprintf(fileID,formatSpec1,vz); # formatSpec2='atom \t %f \t %f \t %f \t %s \n'; # nrows= size(atom_cell,1); # for row = 1:nrows: # fprintf(fileID,formatSpec2,atom_cell{row, :}); # fclose(fileID); # #movefile([name '-nonpolar' ext], pathstr); # cd(oldpath); # top_z=minNP_z(1); return polar, z_thickness, minDiffRate, typeDiff if polar and firstRound: layer_thickness = layer_thickness + 1; minNP_z = np.append(minNP_z,surface_z[-1]); #pdb.set_trace(); data_delete = (atom_coor[:, 2]==surface_z[-1]); data_delete = data_delete[~forDelete]; forDelete= np.squeeze(forDelete | (atom_coor[:, 2]==surface_z[-1])); atom_dist = atom_dist[~data_delete,:]; atom_dist = atom_dist[:,~data_delete]; ele_n = ele_n[~data_delete,:]; ele_n = ele_n[:,~data_delete]; #pdb.set_trace(); surface_n=surface_n-1; surface_z = np.delete(surface_z, -1); #pdb.set_trace(); z_thickness=float("nan"); layer_thickness = float("nan"); #top_z = float("nan"); #perodicity_lower_bound = float("nan"); return polar, z_thickness, minDiffRate, typeDiff
def BnB(filename, cutoff, randseed): G = nx.Graph() f = open('%s.graph'%filename,'r') content = f.readlines() num_vertices = int(content[0].split(" ")[0]) num_edges = int(content[0].split(" ")[1]) for i in range (1, num_vertices+1): G.add_node(i) try: edges = [int(item) for item in content[i].strip().split(" ")] for e in edges: G.add_edge(i,e) except ValueError: pass G_Remaining = dc(G) #best_initial = len(G.nodes()) best_initial = len(min_weighted_vertex_cover(G, None)) degree_sorted_nodes = sorted(G.degree(), key=G.degree().get) V_remaining = [] #V_remaining = set() for item in degree_sorted_nodes: #V_remaining.add(item) V_remaining.append(item) q = Queue.LifoQueue() I = [] q.put((I, V_remaining, G_Remaining)) VC = min_weighted_vertex_cover(G, None) start = time.time() elapsed = 0 while(not q.empty() and elapsed < cutoff): Inc, V_rem, G_rem = q.get() if not G_rem.edges(): if len(Inc) < best_initial: best_initial = len(Inc) VC = Inc else: if V_rem: v = V_rem.pop() if (len(Inc) + len(nx.maximal_matching(G_rem))) <= best_initial: V_I = Inc V_I = V_I + G_rem.neighbors(v) V_R = V_rem V_R = [item for item in V_rem if item not in G_rem.neighbors(v)] G_pass = dc(G_rem) G_pass.remove_nodes_from(G_rem.neighbors(v)) q.put((dc(V_I), dc(V_R), dc(G_pass))) G_rem.remove_node(v) Inc.append(v) if(len(Inc) + len(nx.maximal_matching(G_rem))) <= best_initial: q.put((dc(Inc), dc(V_rem), dc(G_rem))) elapsed = (time.time() - start) output_sol = open('%s_BnB_%d_%d.sol'%(filename, cutoff, randseed), 'w') output_sol.write(str(len(VC)) + "\n" + str(VC).strip('[]')) output_trace = open("%s_BnB_%d_%d.trace" %(filename, cutoff, randseed), 'a') output_trace.write(str(elapsed)+" "+str(len(VC))) print VC print len(VC) print elapsed
def test_single_edge_matching(self): # In the star graph, any maximal matching has just one edge. G = nx.star_graph(5) matching = nx.maximal_matching(G) assert_equal(1, len(matching)) assert_true(nx.is_maximal_matching(G, matching))