5

I have an ADT (PCB aka Process Control Block), I want to put them into a priority queue. How can I do it?

I already used How to put items into priority queues? to have a secondary priority to ensure the correct ordering of the queue. Here I can make the PCB comparable, but in another class, it may not make sense? In that case what might I do?

UPDATE

My code is very similar to that posted https://stackoverflow.com/a/9289760/292291

class PCB:
    ...

# in my class extending `PriorityQueue`
PriorityQueue.put(self, (priority, self.counter, pcb))

I think the problem is pcb is still not comparable here

Community
  • 1
  • 1
Jiew Meng
  • 84,767
  • 185
  • 495
  • 805
  • If you cannot make an object comparable by priority, then insert `(priority, obj)` pairs into the PQ. – Fred Foo Feb 15 '12 at 11:35
  • @larsmans, from the code http://stackoverflow.com/a/9289760/292291, `PriorityQueue.put(self, (priority, self.counter, item))` I have already done something similar – Jiew Meng Feb 15 '12 at 12:12
  • 1
    @JiewMeng: if the priority and counter are always comparable and no two counters ever have the same value, then the entire triple is comparable. – Fred Foo Feb 15 '12 at 12:24
  • @larsman, I am guessing Python cannot assume thats the case? In the mean time, I implemented `__lt__` to make things work now. Still interested to know, if it isnt logical to all comparison logic to class for some reasons, what might I do? The example code given in the link should guarantee uniqueness in the 1st 2 elements of the tuple, but python still complains the ADT is not orderable. I think this is the way Python 3 works, I forgot where I just read it ... – Jiew Meng Feb 15 '12 at 12:42
  • 1
    `f = open('.bashrc'); g = open('.vimrc'); (1, f) < (2, g)` works fine on Python 3.1.3, despite file objects being unorderable. I guess there's some other flaw in your program. You can also wrap your PCB objects in an object type with a custom `__lt__` if you don't want to change your classes, e.g. a `PrioritizedPCB`. – Fred Foo Feb 15 '12 at 13:21
  • @JiewMeng: Please **update** your question rather than add long, complex comments. It you want items to be comparable you must implement `__lt__` and `__gt__`. Is that what you're asking? How to implement the necessary comparisons? – S.Lott Feb 19 '12 at 00:16

1 Answers1

12

OK just to close off this question. Heres what I did:

Make the ADT comparable: Implement __lt__().

def __lt__(self, other):
    selfPriority = (self.priority, self.pid)
    otherPriority = (other.priority, other.pid)
    return selfPriority < otherPriority

This way, I can simply use queue.put(obj)

I found that @larsmans is right in saying

"if the priority and counter are always comparable and no two counters ever have the same value, then the entire triple is comparable"

jiewmeng@JM:~$ python3.2
Python 3.2.2 (default, Sep  5 2011, 21:17:14) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class Test:
...     def __init__(self, name):
...             self.name = name
... 
>>> from queue import PriorityQueue
>>> q = PriorityQueue()

# duplicate priorities triggering unorderable error
>>> q.put((2, Test("test1")))
>>> q.put((1, Test("test1")))
>>> q.put((3, Test("test1")))
>>> q.put((3, Test("test1")))
>>> q.put((3, Test("test2")))
>>> while not q.empty():
...     print(q.get().name)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.2/queue.py", line 195, in get
    item = self._get()
  File "/usr/lib/python3.2/queue.py", line 245, in _get
    return heappop(self.queue)
TypeError: unorderable types: Test() < Test()

# unique priority fields thus avoiding the problem
>>> q = PriorityQueue()
>>> q.put((3, Test("test1")))
>>> q.put((5, Test("test5")))

>>> while not q.empty():
...     print(q.get()[1].name)
... 
test1
test5
Jiew Meng
  • 84,767
  • 185
  • 495
  • 805