def enum_perfect_matching(g): match = maximum_matching_all(g) matches = [match] # m, d = build_d(g, match) if is_perfect_matching(g, match): enum_perfect_matching_iter(matches, g, match) else: print("No perfect matching found!")
def k_factor(G, k, matching_weight="weight"): """Compute a k-factor of G A k-factor of a graph is a spanning k-regular subgraph. A spanning k-regular subgraph of G is a subgraph that contains each vertex of G and a subset of the edges of G such that each vertex has degree k. Parameters ---------- G : NetworkX graph Undirected graph weight: string, optional (default='weight') Edge data key corresponding to the edge weight. Used for finding the max-weighted perfect matching. If key not found, uses 1 as weight. Returns ------- G2 : NetworkX graph A k-factor of G References ---------- .. [1] "An algorithm for computing simple k-factors.", Meijer, Henk, Yurai Núñez-Rodríguez, and David Rappaport, Information processing letters, 2009. """ from networkx.algorithms.matching import max_weight_matching from networkx.algorithms.matching import is_perfect_matching class LargeKGadget: def __init__(self, k, degree, node, g): self.original = node self.g = g self.k = k self.degree = degree self.outer_vertices = [(node, x) for x in range(degree)] self.core_vertices = [(node, x + degree) for x in range(degree - k)] def replace_node(self): adj_view = self.g[self.original] neighbors = list(adj_view.keys()) edge_attrs = list(adj_view.values()) for (outer, neighbor, edge_attrs) in zip(self.outer_vertices, neighbors, edge_attrs): self.g.add_edge(outer, neighbor, **edge_attrs) for core in self.core_vertices: for outer in self.outer_vertices: self.g.add_edge(core, outer) self.g.remove_node(self.original) def restore_node(self): self.g.add_node(self.original) for outer in self.outer_vertices: adj_view = self.g[outer] for neighbor, edge_attrs in list(adj_view.items()): if neighbor not in self.core_vertices: self.g.add_edge(self.original, neighbor, **edge_attrs) break g.remove_nodes_from(self.outer_vertices) g.remove_nodes_from(self.core_vertices) class SmallKGadget: def __init__(self, k, degree, node, g): self.original = node self.k = k self.degree = degree self.g = g self.outer_vertices = [(node, x) for x in range(degree)] self.inner_vertices = [(node, x + degree) for x in range(degree)] self.core_vertices = [(node, x + 2 * degree) for x in range(k)] def replace_node(self): adj_view = self.g[self.original] for (outer, inner, (neighbor, edge_attrs)) in zip(self.outer_vertices, self.inner_vertices, list(adj_view.items())): self.g.add_edge(outer, inner) self.g.add_edge(outer, neighbor, **edge_attrs) for core in self.core_vertices: for inner in self.inner_vertices: self.g.add_edge(core, inner) self.g.remove_node(self.original) def restore_node(self): self.g.add_node(self.original) for outer in self.outer_vertices: adj_view = self.g[outer] for neighbor, edge_attrs in adj_view.items(): if neighbor not in self.core_vertices: self.g.add_edge(self.original, neighbor, **edge_attrs) break self.g.remove_nodes_from(self.outer_vertices) self.g.remove_nodes_from(self.inner_vertices) self.g.remove_nodes_from(self.core_vertices) # Step 1 if any(d < k for _, d in G.degree): raise nx.NetworkXUnfeasible( "Graph contains a vertex with degree less than k") g = G.copy() # Step 2 gadgets = [] for node, degree in list(g.degree): if k < degree / 2.0: gadget = SmallKGadget(k, degree, node, g) else: gadget = LargeKGadget(k, degree, node, g) gadget.replace_node() gadgets.append(gadget) # Step 3 matching = max_weight_matching(g, maxcardinality=True, weight=matching_weight) # Step 4 if not is_perfect_matching(g, matching): raise nx.NetworkXUnfeasible( "Cannot find k-factor because no perfect matching exists") for edge in g.edges(): if edge not in matching and (edge[1], edge[0]) not in matching: g.remove_edge(edge[0], edge[1]) for gadget in gadgets: gadget.restore_node() return g
def plan(self): agent_state = self.env.x task_state = self.env.tasks print(agent_state, 'agent state') print(task_state, 'task state') n=len(agent_state) wt_array=np.zeros((n,n)) for i in range(0,n): for j in range(0,n): wt_array[i][j] = math.sqrt((agent_state[i][0] - task_state[j][0])**2 + (agent_state[i][1] - task_state[j][1])**2) Inf = float('inf') wts=scipy.sparse.lil_matrix(wt_array) #types of sparse matrix? #is Inf okay B=bipartite.matrix.from_biadjacency_matrix(wts) #node labels left_nodes, right_nodes = bipartite.sets(B) l_wts = {node: min(wts.toarray()[i]) for i, node in enumerate(left_nodes)} r_wts = {node: 0 for node in right_nodes} #equality subgraph eq_subgraph = nx.Graph() eq_subgraph.add_nodes_from(left_nodes, bipartite=0) eq_subgraph.add_nodes_from(right_nodes, bipartite=1) edges = ((edge[0], edge[1], {'weight': edge[2]['weight']}) for edge in B.edges(data=True) #with wieghts if (l_wts[edge[0]] + r_wts[edge[1]] == edge[2]['weight'])) # eq_subgraph.update(edges) eq_subgraph.add_edges_from(edges) # maximum matching Max_match = bipartite.matching.hopcroft_karp_matching(eq_subgraph, top_nodes=left_nodes) #Min vertex cover Min_vertex = bipartite.matching.to_vertex_cover(eq_subgraph, Max_match, top_nodes=left_nodes) while(not matching.is_perfect_matching(B,Max_match)): Rc = left_nodes.intersection(Min_vertex) Pc = right_nodes.intersection(Min_vertex) Rc_not = left_nodes.difference(Rc) Pc_not = right_nodes.difference(Pc) E_cand={} # Step 1(a): for i in Rc_not: min_slack = Inf for j in Pc_not: j_n = j-n if wt_array[i][j_n] != Inf: slack = wt_array[i][j_n]-l_wts[i]-r_wts[j] if slack < min_slack: min_slack = slack min_j = j E_cand[i] = min_j # Step 1(b): min_slack = Inf for i in E_cand.keys(): j_n=E_cand[i]-n j=E_cand[i] slack = wt_array[i][j_n]-l_wts[i]-r_wts[j] if slack < min_slack: min_slack = slack i_new = i delta_slack = min_slack if i_new in Rc: l_wts[i_new]= l_wts[i_new] - delta_slack if E_cand[i_new] in Pc_not: r_wts[E_cand[i_new]]= r_wts[E_cand[i_new]] + delta_slack # Step 2: # new_edge eq_subgraph.add_edge(i_new, E_cand[i_new], weight= wt_array[i_new][E_cand[i_new]-n]) # maximum matching Max_match = bipartite.matching.hopcroft_karp_matching(eq_subgraph, top_nodes=left_nodes) print(Max_match, 'Maximum matching') #Min vertex cover Min_vertex = bipartite.matching.to_vertex_cover(eq_subgraph, Max_match, top_nodes=left_nodes) m=list(Max_match.values()) l = [[x-n] for x in m] print(l[0:n], 'Allocation list ret') return l[0:n]