Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hopcroft–Karp algorithm in Python

I am trying to implement the Hopcroft Karp algorithm in Python using networkx as graph representation.

Currently I am as far as this:

#Algorithms for bipartite graphs

import networkx as nx
import collections

class HopcroftKarp(object):
    INFINITY = -1

    def __init__(self, G):
        self.G = G

    def match(self):
        self.N1, self.N2 = self.partition()
        self.pair = {}
        self.dist = {}
        self.q = collections.deque()

        #init
        for v in self.G:
            self.pair[v] = None
            self.dist[v] = HopcroftKarp.INFINITY

        matching = 0

        while self.bfs():
            for v in self.N1:
                if self.pair[v] and self.dfs(v):
                    matching = matching + 1

        return matching

    def dfs(self, v):
        if v != None:
            for u in self.G.neighbors_iter(v):
                if self.dist[ self.pair[u] ] == self.dist[v] + 1 and self.dfs(self.pair[u]):
                    self.pair[u] = v
                    self.pair[v] = u

                    return True

            self.dist[v] = HopcroftKarp.INFINITY
            return False

        return True

    def bfs(self):
        for v in self.N1:
            if self.pair[v] == None:
                self.dist[v] = 0
                self.q.append(v)
            else:
                self.dist[v] = HopcroftKarp.INFINITY

        self.dist[None] = HopcroftKarp.INFINITY

        while len(self.q) > 0:
            v = self.q.pop()
            if v != None:
                for u in self.G.neighbors_iter(v):
                    if self.dist[ self.pair[u] ] == HopcroftKarp.INFINITY:
                        self.dist[ self.pair[u] ] = self.dist[v] + 1
                        self.q.append(self.pair[u])

        return self.dist[None] != HopcroftKarp.INFINITY


    def partition(self):
        return nx.bipartite_sets(self.G)

The algorithm is taken from http://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm However it does not work. I use the following test code

G = nx.Graph([
(1,"a"), (1,"c"),
(2,"a"), (2,"b"),
(3,"a"), (3,"c"),
(4,"d"), (4,"e"),(4,"f"),(4,"g"),
(5,"b"), (5,"c"),
(6,"c"), (6,"d")
])

matching = HopcroftKarp(G).match()

print matching

Unfortunately this does not work, I end up in an endless loop :(. Can someone spot the error, I am out of ideas and I must admit that I have not yet fully understand the algorithm, so it is mostly an implementation of the pseudo code on wikipedia

like image 205
Simon Avatar asked Jan 15 '11 00:01

Simon


2 Answers

The line

if self.pair[v] and self.dfs(v):

should be

if self.pair[v] is None and self.dfs(v):

as per the pseudo-code on the Wikipedia page. The only other problem I see is that you are using the deque as a stack and you want to use it as a queue. To remedy that, you just need to popleft rather than pop (which pops right). So the line

v = self.q.pop()

should be

v = self.q.popleft()

Hopefully everything else works. I was just checking that your Python code works in the same manner as the pseudocode on Wikipedia so hopefully that pseudocode is correct.

like image 53
Justin Peel Avatar answered Nov 08 '22 10:11

Justin Peel


In python there is a package for this algorithm. HopcroftKarp, you can directly use that package for your implementation.

like image 43
Gourav Kumar Avatar answered Nov 08 '22 11:11

Gourav Kumar