Skip to content

Commit fb57e95

Browse files
rajatjain1997antmarakis
authored andcommitted
Reworked PriorityQueue and Added Tests (#1025)
* Reworked PriorityQueue spec Modified: - Priority Queue methods: queue[elem] now returns the first value of elem stored in queue elem in queue now correctly returns whether a copy of element is present regardless of the function value. Apparently the bug was introduced while trying to meet heapq spec del queue[elem] deletes the first instance of elem in queue correctly - Algorithms Same change in best_first_graph_search in romania_problem.py and search.py to make them compatible with the new spec - Tests Introduced 3 tests in test_utils.py to comprehensively test PriorityQueue's new spec * Reworked PriorityQueue spec Modified: - Priority Queue methods: queue[elem] now returns the first value of elem stored in queue elem in queue now correctly returns whether a copy of element is present regardless of the function value. Apparently the bug was introduced while trying to meet heapq spec del queue[elem] deletes the first instance of elem in queue correctly - Algorithms Same change in best_first_graph_search in romania_problem.py and search.py to make them compatible with the new spec - Tests Introduced 3 tests in test_utils.py to comprehensively test PriorityQueue's new spec
1 parent 3b0faac commit fb57e95

File tree

6 files changed

+54
-12
lines changed

6 files changed

+54
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ nosetests.xml
4444
coverage.xml
4545
*,cover
4646
.hypothesis/
47+
*.pytest_cache
4748

4849
# Translations
4950
*.mo

gui/romania_problem.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,9 +538,8 @@ def best_first_graph_search(problem, f):
538538
if child.state not in explored and child not in frontier:
539539
frontier.append(child)
540540
elif child in frontier:
541-
incumbent = frontier[child]
542-
if f(child) < f(incumbent):
543-
del frontier[incumbent]
541+
if f(child) < frontier[child]:
542+
del frontier[child]
544543
frontier.append(child)
545544
display_frontier(frontier)
546545
if counter % 3 == 2 and counter >= 0:

search.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,8 @@ def best_first_graph_search(problem, f):
275275
if child.state not in explored and child not in frontier:
276276
frontier.append(child)
277277
elif child in frontier:
278-
incumbent = frontier[child]
279-
if f(child) < f(incumbent):
280-
del frontier[incumbent]
278+
if f(child) < frontier[child]:
279+
del frontier[child]
281280
frontier.append(child)
282281
return None
283282

tests/.pytest_cache/v/cache/lastfailed

Whitespace-only changes.

tests/test_utils.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,43 @@ def test_expr():
273273
assert (expr('GP(x, z) <== P(x, y) & P(y, z)')
274274
== Expr('<==', GP(x, z), P(x, y) & P(y, z)))
275275

276+
def test_min_priorityqueue():
277+
queue = PriorityQueue(f=lambda x: x[1])
278+
queue.append((1,100))
279+
queue.append((2,30))
280+
queue.append((3,50))
281+
assert queue.pop() == (2,30)
282+
assert len(queue) == 2
283+
assert queue[(3,50)] == 50
284+
assert (1,100) in queue
285+
del queue[(1,100)]
286+
assert (1,100) not in queue
287+
queue.extend([(1,100), (4,10)])
288+
assert queue.pop() == (4,10)
289+
assert len(queue) == 2
290+
291+
def test_max_priorityqueue():
292+
queue = PriorityQueue(order='max', f=lambda x: x[1])
293+
queue.append((1,100))
294+
queue.append((2,30))
295+
queue.append((3,50))
296+
assert queue.pop() == (1,100)
297+
298+
def test_priorityqueue_with_objects():
299+
class Test:
300+
def __init__(self, a, b):
301+
self.a = a
302+
self.b = b
303+
def __eq__(self, other):
304+
return self.a==other.a
305+
306+
queue = PriorityQueue(f=lambda x: x.b)
307+
queue.append(Test(1,100))
308+
other = Test(1,10)
309+
assert queue[other]==100
310+
assert other in queue
311+
del queue[other]
312+
assert len(queue)==0
276313

277314
if __name__ == '__main__':
278315
pytest.main()

utils.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -773,18 +773,24 @@ def __len__(self):
773773
"""Return current capacity of PriorityQueue."""
774774
return len(self.heap)
775775

776-
def __contains__(self, item):
777-
"""Return True if item in PriorityQueue."""
778-
return (self.f(item), item) in self.heap
776+
def __contains__(self, key):
777+
"""Return True if the key is in PriorityQueue."""
778+
return any([item == key for _, item in self.heap])
779779

780780
def __getitem__(self, key):
781-
for _, item in self.heap:
781+
"""Returns the first value associated with key in PriorityQueue.
782+
Raises KeyError if key is not present."""
783+
for value, item in self.heap:
782784
if item == key:
783-
return item
785+
return value
786+
raise KeyError(str(key) + " is not in the priority queue")
784787

785788
def __delitem__(self, key):
786789
"""Delete the first occurrence of key."""
787-
self.heap.remove((self.f(key), key))
790+
try:
791+
del self.heap[[item == key for _, item in self.heap].index(True)]
792+
except ValueError:
793+
raise KeyError(str(key) + " is not in the priority queue")
788794
heapq.heapify(self.heap)
789795

790796

0 commit comments

Comments
 (0)