'Dijkstra\'s shortest paths algorithm.
See also:
- http://en.wikipedia.org/wiki/Dijkstra\'s_algorithm'

def _rank_cycle_function(self, cycle, function, ranks):

    import heapq
    Q = []
    Qd = {}
    p = {}
    visited = set([function])
    ranks[function] = 0
    for call in compat_itervalues(function.calls):
        if (call.callee_id != function.id):
            callee = self.functions[call.callee_id]
            if (callee.cycle is cycle):
                ranks[callee] = 1
                item = [ranks[callee], function, callee]
                heapq.heappush(Q, item)
                Qd[callee] = item
    while Q:
        (cost, parent, member) = heapq.heappop(Q)
        if (member not in visited):
            p[member] = parent
            visited.add(member)
            for call in compat_itervalues(member.calls):
                if (call.callee_id != member.id):
                    callee = self.functions[call.callee_id]
                    if (callee.cycle is cycle):
                        member_rank = ranks[member]
                        rank = ranks.get(callee)
                        if (rank is not None):
                            if (rank > (1 + member_rank)):
                                rank = (1 + member_rank)
                                ranks[callee] = rank
                                Qd_callee = Qd[callee]
                                Qd_callee[0] = rank
                                Qd_callee[1] = member
                                heapq._siftdown(Q, 0, Q.index(Qd_callee))
                        else:
                            rank = (1 + member_rank)
                            ranks[callee] = rank
                            item = [rank, member, callee]
                            heapq.heappush(Q, item)
                            Qd[callee] = item
