#! /usr/local/bin/python -O

# more complex implementation of topological sort

LOOPERROR = "LOOPERROR"

def tsort(pairs):
    from kjbuckets import kjGraph, kjSet
    G = kjGraph(pairs)
    Gt = ~G # transpose
    sources = kjSet(G.keys())
    dests = kjSet(G.values())
    all = (sources+dests).items()
    total = len(all)
    endpoints = dests - sources
    for i in xrange(total-1, -1, -1):
        #print i, endpoints
        if not endpoints:
           raise LOOPERROR, "loop detected"
        choice = endpoints.choose_key()
        for n in Gt.neighbors(choice):
            G.delete_arc(n,choice)
            if not G.has_key(n):
               endpoints[n] = n
        del endpoints[choice]
        all[i] = choice
    return all

 
if __name__=="__main__":
   list = [ (1,2), (3,4), (1,6), (6,3), (3,9), (4,2) ]
   print tsort(list)
   try:
      list = [ (1,2), (3,4), (1,6), (6,3), (3,9), (3,1) ]
      print tsort(list)
      print "WHOOPS: loop 1-6-3-1 not detected"
   except LOOPERROR:
      print "loop error as expected"

