A* Search in Python Priority Queue - python

I am trying to write an A* search to solve a maze in Python, however I am struggling to find a built in priority queue that works for this. I am using PriorityQueue at the moment, but it offers no functionality in order to change an items priority, which is a problem in the commented section at the bottom of the algorithm (in the else if statement).
Does anyone have any idea what I could do in that else if block, or what built in priority queue would give me this functionality?
def A_search(maze, start, end):
expanded = 0 # use to track number of nodes expanded by the algorithm
node1 = Node(start,0)
frontier = PriorityQueue()
frontier.put((dist_to_goal(node1,end) + node1.get_cost(), node1))
visited = []
in_frontier = [] # keep track of items in frontier, PriorityQueue has no way to peek
in_frontier.append(node1)
while(True):
if(frontier == []):
return(None,expanded)
curr = (frontier.get())[1]
in_frontier.remove(curr)
expanded += 1
if(curr.get_loc() == end):
return(curr,expanded)
visited.append(curr.get_loc())
neighbors = find_neighbors(maze, curr.get_loc())
for neighbor in neighbors:
node_n = Node(neighbor,node1.get_cost()+1)
node_n.parent = curr
if(neighbor not in visited) and (node_n not in in_frontier):
frontier.put((dist_to_goal(node_n,end) + node1.get_cost(), node_n))
in_frontier.append(node_n)
# else if node_n is in frontier w/ a higher path cost then replace it w/ current

The closest you will find in the built-in libraries is heapq.
After changing the priority you need to call either heapq.heapify (costs O(n) time but will not change A* overall complexity) or use the internal heapq._siftdown function at O(log n) time.

Updating the item priority, is discussed in the official python documentation about the heapq module in the priority queue implementation notes: https://docs.python.org/3.7/library/heapq.html#priority-queue-implementation-notes
Using these notes, I managed to write my own PriorityQueue Implementation that supports adding a task and updating it's priority if it exists. It consists in using an entry_finder dict which point to tasks in the priority queue. Updating a task's priority, simply consists in marking the existing task as deleted and inserting it with the new priority.
In this implementation, you can use method add_task
class PriorityQueue():
REMOVED = '<removed-task>'
def __init__(self):
self.pq = []
self.entry_finder = {}
self.counter = itertools.count()
def add_task(self, task, priority=0):
if task in self.entry_finder:
self.remove_task(task)
count = next(self.counter)
entry = [priority, count, task]
self.entry_finder[task] = entry
heappush(self.pq, entry)
def remove_task(self, task):
entry = self.entry_finder.pop(task)
entry[-1] = self.REMOVED
def pop_task(self):
while self.pq:
priority, count, task = heappop(self.pq)
if task is not self.REMOVED:
del self.entry_finder[task]
return task
return None

Related

Why is my tree-node function producing Null when I run an array through it?

I am working on the LeetCode problem 104. Maximum Depth of Binary Tree:
Given the root of a binary tree, return its maximum depth.
A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
My attempt is not working: I first add the root to a queue (if root is not None), and then process it, by adding its children to the queue.
While doing this, I keep a counter, and each time I add a child node, I increment the counter by 1. When both left and right child exist, I will only increment the counter by 1.
from collections import deque
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def max_depth(self,root):
counter = 1
queue = deque
if not root:
return 0
else:
queue.append(root)
while queue:
root = queue.popleft()
if root.left:
queue.append(root.left)
counter +=1
if root.right:
queue.append(root.right)
if root.left:
continue
else:
counter +=1
return counter
However, when I run the above on LeetCode, for an input of say [3,9,20,null,null,15,7], I get 'None' as a result.
Is it because I have structured the function to not take a list as an input?
Is it because I have structured the function to not take a list as an input?
No. This may be confusing, but on LeetCode the raw list representation of the input is translated to an instance of TreeNode before your function is called. So you should never have to deal with this list structure. It is merely the common input format that LeetCode uses across the different programming languages. But the conversion to the target language's data structure is done for you before your implementation is called.
Your code produces an error on the first call of queue.append because of this line:
queue = deque
This is wrong, as this makes queue a synonym for the class deque. But it should be an instance of it, so do:
queue = deque()
With that fix, the function does not return None.
However, its logic is not correct:
I keep a counter, and each time I add a child node, I increment the counter by 1. When both left and right child exist, I will only increment the counter by 1.
This practically means that you count the number of nodes that have at least one child, i.e. you count the number of internal nodes of the tree.
This is not correct. For instance, the following tree has 7 internal nodes:
___ 10 __
/ \
5 14
/ \ / \
1 8 12 20
/ \ / \ / \ / \
0 2 6 9 11 13 18 22
Obviously, 7 is not the correct answer. It should be 4 in this case.
Your queue-based solution will visit the nodes level by level, but you don't have any information about when you pass from one level to the next.
You can solve this by using two (standard) lists: the first list will have all the nodes from one level, and the second list will collect those from the next level. When that is done you know you have processed one level. Then you make the second list the first, and empty the second. Then you can restart this process for as long as there are nodes to process:
class Solution:
def maxDepth(self, root: TreeNode) -> int:
counter = 0
queue = []
if root:
queue.append(root)
while queue:
counter +=1
nextlevel = []
for root in queue:
if root.left:
nextlevel.append(root.left)
if root.right:
nextlevel.append(root.right)
queue = nextlevel
return counter
Making it a bit more compact, it can be:
class Solution:
def maxDepth(self, root: TreeNode) -> int:
counter = 0
if root:
queue = [root]
while queue:
counter +=1
queue = [root.left for root in queue if root.left
] + [root.right for root in queue if root.right]
return counter
You can also go for a depth-first traversal instead of the breadth-first traversal you were going for:
class Solution:
def maxDepth(self, root: TreeNode) -> int:
return 1 + max(self.maxDepth(root.left),
self.maxDepth(root.right)) if root else 0

Rotate a linked list k times (Python)

While practicing for my final in Python programming I ran into this question "def rotaten" of rotating k times. The problem says that k can range from 0 to any positive integer number (even greater than list size, if k < 0 raise ValueError
and it must execute in O( (n-k)%n ) where n is the length of the list. It also has the following warnings:
WARNING: DO NOT call .rotate() k times !!!!
WARNING: DO NOT try to convert whole linked list to a python list
WARNING: DO NOT swap node data or create nodes
The problem is that I'm not understanding the solution given. Is there an easier way to solve this problem? Thank you in advance
class Node:
def __init__(self,initdata):
self._data = initdata
self._next = None
def get_data(self):
return self._data
def get_next(self):
return self._next
def set_data(self,newdata):
self._data = newdata
def set_next(self,newnext):
self._next = newnext
class LinkedList:
def rotaten(self, k):
if k < 0:
raise ValueError
if self._size > 1:
m = k % self._size
if m > 0 and m < self._size:
current = self._head
for i in range(self._size - m - 1):
current = current.get_next()
chain_b = current.get_next()
old_head = self._head
old_last = self._last
self._last = current
self._last.set_next(None)
self._head = chain_b
old_last.set_next(old_head)
The easiest ways are forbidden
warning forbids implementing the singular rotation, then calling it repeatedly
warning forbids using native python structure - python has list built-in in basic collections list(), which can be then transformed to a deque, which can then be rotated by popping from the end and inserting the same node to the beginning.
warning is preventing you from making your life easier by creating some other nodes or worse - copying data. (copying data from one node to another would remove any advantage you had from storing the data into the lists in the first place)
The example solution is basically this:
Take the current first node(head of the list) and the tail node which is stored in the List structure. (the bookkeeping of the example list consists of holding the head and tail, the rest is done in the nodes themselves)
Find the k-th node - so that you rotate the whole list at once. This is where the list needs to be cut.
Add the last node as the new head, doing all the necessary reference-linking and unlinking. (Which is I guess the point of this question - to test if you understand the references. In C these would be pointers, python has the references implicitly.)
So as far as the linked lists go, this is the most straightforward solution with the requested O((n-k)%n) complexity.
Good luck with your pointers :-).

Uniform Cost Search In Romania Map problem

I have written this code. This is a code of Uniform COst search. I have to find the path between Arad and Bucharest. My problem is that my code is giving the correct total cost that is 418. But I can not figure out how to find the path that is giving this cost. Any help is appreciated.
from queue import PriorityQueue
class Graph:
def __init__(self):
self.edges={"Arad":["Zerind","Timisoara","Sibiu"],"Zerind":["Oradea"],"Oradea":["Sibiu"],"Timisoara":["Lugoj"],"Lugoj":["Mehadia"],"Mehadia":["Dobreta"],"Dobreta":["Craiova"],"Sibiu":["Fagaras","RimnicuVilcea"],"Craiova":["RimnicuVilcea","Pitesti"],"RimnicuVilcea":["Craiova","Pitesti"],"Fagaras":["Bucharest"],"Pitesti":["Bucharest"],"Bucharest":["Giurgiu","Urziceni"],"Urziceni":["Hirsova","Vaslui"],"Hirsova":["Eforie"],"Vaslui":["Lasi"],"Lasi":["Neamt"]}
self.weights={"AradZerind":75,"ZerindOradea":71,"AradTimisoara":118,"TimisoaraLugoj":111,"LugojMehadia":70,"MehadiaDobreta":75,"AradSibiu":140,"OradeaSibiu":151,"DobretaCraiova":120,"CraiovaRimnicuVilcea":146,"CraiovaPitesti":138,"SibiuFagaras":99,"SibiuRimnicuVilcea":80,"RimnicuVilceaPitesti":97,"RimnicuVilceaCraiova":146,"FagarasBucharest":211,"PitestiBucharest":101,"BucharestGiurgiu":90,"BucharestUrziceni":85,"UrziceniHirsova":98,"HirsovaEforie":86,"UrziceniVaslui":142,"VasluiLasi":92,"LasiNeamt":87}
def neighbors(self,node):
return self.edges[node]
def get_cost(self,from_node,to_node):
return self.weights[(from_node + to_node)]
def ucs(graph, start, goal):
global total_cost
visited = set()
path=[]
queue = PriorityQueue()
queue.put((0, start))
while queue:
cost, node = queue.get()
if node not in visited:
visited.add(node)
if node == goal:
return visited
for i in graph.neighbors(node):
if i not in visited:
total_cost = cost + graph.get_cost(node, i)
queue.put((total_cost, I)
graph=Graph()
s=ucs(graph,"Arad","Bucharest")
print(s)
You can use initialize your (priority) queue like this:
queue = PriorityQueue()
queue.put([0,[start]])
Here, start is a tuple representing the starting state or anything you want to represent in your way.
Then unpack it inside the while loop:
cost,path = queue.get()
x,y=path[-1]
You don't need to define the path var in advance.
When the goal state is reached, instead of returning the cost, just print(cost) or whatever var you want to print and return the path:
x,y=path[-1]
And, to update it when we are traversing the adjacency list of each node, you can do this:
queue.put([costx,path + [(x2, y2)]])
If you want to keep track of many things, you can keep it inside the 'priorityQueue() (your queue).
I can add the code if you want but maybe that won't be necessary.

Python: Using my heap in a priority queue implementation

I am having real trouble using my custom-made heap class functions to be used in my Priority Queue class. I am having trouble on what functions from my heap class to use for my "enqueue", "dequeue", "front" and "size" functions for my PriorityQueue. I know for "enqueue" I need to use my insert function, but I don't know how to go about this because I have a priority. Could someone help me out what I need to do in order to make my PriorityQueue class to use the functions from my Heap class in order to work properly? I have been stuck on this for awhile and I keep finding answers that include using the built in python functions such as queue and heapq.
class Heap(object):
def __init__(self, items=None):
'''Post: A heap is created with specified items.'''
self.heap = [None]
if items is None:
self.heap_size = 0
else:
self.heap += items
self.heap_size = len(items)
self._build_heap()
def size(self):
'''Post: Returns the number of items in the heap.'''
return self.heap_size
def _heapify(self, position):
'''Pre: Items from 0 to position - 1 satisfy the Heap property.
Post: Heap Property is satisfied for the entire heap.'''
item = self.heap[position]
while position * 2 <= self.heap_size:
child = position * 2
# If the right child, determine the maximum of two children.
if (child != self.heap_size and self.heap[child+1] > self.heap[child]):
child += 1
if self.heap[child] > item:
self.heap[position] = self.heap[child]
position = child
else:
break
self.heap[position] = item
def delete_max(self):
'''Pre: Heap property is satisfied
Post: Maximum element in heap is removed and returned. '''
if self.heap_size > 0:
max_item = self.heap[1]
self.heap[1] = self.heap[self.heap_size]
self.heap_size -= 1
self.heap.pop()
if self.heap_size > 0:
self._heapify(1)
return max_item
def insert(self, item):
'''Pre: Heap Property is Satisfied.
Post: Item is inserted in proper location in heap.'''
self.heap_size += 1
# extend the length of the list.
self.heap.append(None)
position = self.heap_size
parent = position // 2
while parent > 0 and self.heap[parent] < item:
# Move the item down.
self.heap[position] = self.heap[parent]
position = parent
parent = position // 2
# Puts the new item in the correct spot.
self.heap[position] = item
def _build_heap(self):
''' Pre: Self.heap has values in 1 to self.heap_size
Post: Heap property is satisfied for entire heap. '''
# 1 through self.heap_size.
for i in range(self.heap_size // 2, 0, -1): # Stops at 1.
self._heapify(i)
def heapsort(self):
'''Pre: Heap Property is satisfied.
Post: Items are sorted in self.heap[1:self.sorted_size].'''
sorted_size = self.heap_size
for i in range(0, sorted_size -1):
# Since delete_max calls pop to remove an item, we need to append a dummy value to avoid an illegal index.
self.heap.append(None)
item = self.delete_max()
self.heap[sorted_size - i] = item
So this is working but like I previously stated I am having trouble on how to make a priority queue out of this? I know asking for code is wrong, but I'm desperate could anyone help me out here? I have the basic rundown on what I want my priority code to do..
#PriorityQueue.py
from MyHeap import Heap
class PriorityQueue(object):
def __init__(self):
self.heap = None
def enqueue(self, item, priority):
'''Post: Item is inserted with specified priority in the PQ.'''
self.heap.insert((priority, item))
def first(self):
'''Post: Returns but does not remove the highest priority item from the PQ.'''
return self.heap[0]
def dequeue(self):
'''Post: Removes and returns the highest priority item from the PQ.'''
if self.heap is None:
raise ValueError("This queue is empty.")
self.heap.delete_max()
def size(self):
'''Post: Returns the number of items in the PQ.'''
return self.size
This is what I got so far but I do not know if it is entirely correct. Could anyone help me out?
I edited my code to the most current version of it.
Since this is presumably homework, all I can do is give hints, which is often easier done as comments. Since this ended up being a fairly thorough series of hints I'm summarizing them as an answer here.
For the most part, methods in your PriorityQueue class will map to methods you've already implemented in your Heap class:
PriorityQueue.enqueue() maps pretty easily to Heap.insert()
PriorityQueue.first() does not have a corresponding heap method, but can still be implemented in one line. You just need to return the maximum value, which will always be at a specific place in your heap.
PriorityQueue.dequeue() is a little more complicated. It needs to save the value of the top item first so that it can return it after calling heap.delete_max()
The heap class already has a size() method, which PriorityQueue.size() can call, instead of maintaining a separate size variable within the PriorityQueue class.
Additionally, you need an init function, This should create a new Heap object that will be maintained by the class.
In order to make an iterator, you'll need to make a new class. It will need to maintain an integer variable (let's call it self.index), indicating its current place in the queue. You'll also want a method that increases self.index and returns the value that was at the previous index location. That should be about it.

Making a priority queue using a Heap. Without using "queue" or "heapq"

I have made a heap class and I am trying to make a PriorityQueue class as well so both of them can work together. However, I need help on the Priority Queue part of my code. I have already made a working Heap. I tried looking up help on the internet but I keep getting answers with people using either the "queue" or "heapq" python implementation. Could anyone help me on how to make a working Priority Queue class? I have the basic function names written down but I have no idea on where to go from there. Please I have been stuck on this for awhile and really need some help. Here is my working Heap Code.
class Heap(object):
def __init__(self, items=None):
'''Post: A heap is created with specified items.'''
self.heap = [None]
if items is None:
self.heap_size = 0
else:
self.heap += items
self.heap_size = len(items)
self._build_heap()
def size(self):
'''Post: Returns the number of items in the heap.'''
return self.heap_size
def _heapify(self, position):
'''Pre: Items from 0 to position - 1 satisfy the Heap property.
Post: Heap Property is satisfied for the entire heap.'''
item = self.heap[position]
while position * 2 <= self.heap_size:
child = position * 2
# If the right child, determine the maximum of two children.
if (child != self.heap_size and self.heap[child+1] > self.heap[child]):
child += 1
if self.heap[child] > item:
self.heap[position] = self.heap[child]
position = child
else:
break
self.heap[position] = item
def delete_max(self):
'''Pre: Heap property is satisfied
Post: Maximum element in heap is removed and returned. '''
if self.heap_size > 0:
max_item = self.heap[1]
self.heap[1] = self.heap[self.heap_size]
self.heap_size -= 1
self.heap.pop()
if self.heap_size > 0:
self._heapify(1)
return max_item
def insert(self, item):
'''Pre: Heap Property is Satisfied.
Post: Item is inserted in proper location in heap.'''
self.heap_size += 1
# extend the length of the list.
self.heap.append(None)
position = self.heap_size
parent = position // 2
while parent > 0 and self.heap[parent] < item:
# Move the item down.
self.heap[position] = self.heap[parent]
position = parent
parent = position // 2
# Puts the new item in the correct spot.
self.heap[position] = item
def _build_heap(self):
''' Pre: Self.heap has values in 1 to self.heap_size
Post: Heap property is satisfied for entire heap. '''
# 1 through self.heap_size.
for i in range(self.heap_size // 2, 0, -1): # Stops at 1.
self._heapify(i)
def heapsort(self):
'''Pre: Heap Property is satisfied.
Post: Items are sorted in self.heap[1:self.sorted_size].'''
sorted_size = self.heap_size
for i in range(0, sorted_size -1):
# Since delete_max calls pop to remove an item, we need to append a dummy value to avoid an illegal index.
self.heap.append(None)
item = self.delete_max()
self.heap[sorted_size - i] = item
So this is working but like I previously stated I am having trouble on how to make a priority queue out of this? I know asking for code is wrong, but I'm desperate could anyone help me out here? I have the basic rundown on what I want my priority code to do..
#PriorityQueue.py
from MyHeap import Heap
class PriorityQueue(object):
def enqueue(self, item, priority):
'''Post: Item is inserted with specified priority in the PQ.'''
def first(self):
'''Post: Returns but does not remove the highest priority item from the PQ.'''
def dequeue(self):
'''Post: Removes and returns the highest priority item from the PQ.'''
def size(self):
'''Post: Returns the number of items in the PQ.'''
return Heap.heap_size
I think the key idea you're missing to implement your PriorityQueue class is that each PriorityQueue instance should have a Heap instance as an attribute. Set it up in __init__:
class PriorityQueue(object):
def __init__(self)
self.heap = Heap()
When a user makes a call to a PriorityQueue method, that method will mostly just make a call to a method of self.heap, with just a little extra work modifying the arguments or the return value. The items to insert into the heap should probably be (priority, value) tuples, since they will compare appropriately (higher priority items comparing higher).
Note that if you compare code written for heapq with your Heap, you'll need to modify the logic for the indexes and priorities, since heapq implements a zero-indexed min-heap, and your code implements a one-indexed max-heap.

Categories

Resources