Пример #1
0
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!")
Пример #2
0
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
Пример #3
0
    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]