0

I am using a simple heapq in python with custom elements on which I implemented the lt function.

class Edge:
    def __init__(self, cost, u, v):
        self.u = u
        self.v = v
        self.cost = cost
    def weight(self):
        w = self.cost
        v = self.v
        while v.parent is not None:
            w += v.const
            v = v.parent
        return w

    def __lt__(self, other):
        return self.weight() < other.weight()

Then I keep a heap of these elements in another array called P:

class Vertex:
    def __init__(self, node=None):
        #other stuff omited ##### 
        self.P = []

    def add_incoming_nodes(self, subgraph):
        for node, costs in subgraph.items():
            #if costs[self.vertex] is not 0: #node is not self
            #push endpoints of the edge from another vertex to this vertex
            heapq.heappush(self.P, Edge(costs[self.vertex], node, self))

The problem is that when I heappop an element, I would expect it to be the smallest element in my array right ? But this assertion here fails

#select arbitrary vertex
a = all_nodes[0]
while a.P: #while P[a] is not ∅
    edge = heapq.heappop(a.P)
    for a_edge in a.P: 
        assert edge.weight() < a_edge.weight()
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Traoré Moussa
  • 433
  • 1
  • 6
  • 22
  • documentation states that pop removes the smallest, so your assertion must be flawed somewhere. Since you define the `_lt_`, you should do just `edge < a_edge` no? – Yuca Oct 04 '18 at 13:22
  • @Yuca it would be the same. I just went a step ahead and called the functions myself. – Traoré Moussa Oct 04 '18 at 13:26
  • if you assert for less equal, does it still fail? – Yuca Oct 04 '18 at 13:28
  • @Yuca yes it still fails .. although I dont have eq and le implemented – Traoré Moussa Oct 04 '18 at 13:30
  • 1
    @TraoréMoussa: Side-note: Likely not the problem here, but I'd suggest defining `__eq__` and [decorating your class with `functools.total_ordering`](https://docs.python.org/3/library/functools.html#functools.total_ordering) (to define all the other comparators in terms of `__eq__` and `__lt__`), in case one of the other comparison functions is used. While `__lt__` is officially all you need for sorting, virtually anything else in Python is going to expect to be able to use all of the comparators if it can use any of them. – ShadowRanger Oct 04 '18 at 13:30
  • 2
    since I don't have data I can only speculate: your assertion will fail if you have two minimal values – Yuca Oct 04 '18 at 13:31
  • 1
    @Yuca is spot on, although asserting for `<=` should have fixed the `AssertionError` in case of 2 (or more) minimal values – DeepSpace Oct 04 '18 at 13:31
  • @DeepSpace so I would need to implement eq and all the others ? – Traoré Moussa Oct 04 '18 at 13:33
  • 1
    @TraoréMoussa: Like I said, you need to implement `__eq__`, and apply [the `total_ordering` decorator](https://docs.python.org/3/library/functools.html#functools.total_ordering) to your class. With `__eq__`, Python 3 provides a default `__ne__` automatically, and `total_ordering` will then provide `__le__`, `__ge__` and `__gt__` in terms of `__lt__` without you needing to write them yourself. – ShadowRanger Oct 04 '18 at 13:35
  • @ShadowRanger I am looking into it :) – Traoré Moussa Oct 04 '18 at 13:49
  • also, I suggest you change the title of your question once this is resolved since you're assuming the ordered nature is not working, but you might be wrong :) – Yuca Oct 04 '18 at 13:55
  • @Yucaok i will do :))) thank you so much for ur intuition – Traoré Moussa Oct 04 '18 at 13:56
  • let us know how it ends! :) – Yuca Oct 04 '18 at 14:02
  • 1
    @Yuca now my assertion passed. I will post the answer in a minute ! Thanks a lot my deer StackOverflow friends – Traoré Moussa Oct 04 '18 at 14:11

0 Answers0