The following is pseudocode implement depth-first search(DFS) with one stack and a large table to mark visited nodes:
DFS(N0):
StackInit(S)
S.push((N0, null))
if isGoal(N0) then do
return true
markVisited(N0)
S.push((null, N0))
while !isEmpty(S) then do
(N, parent) := S.pop()
R := next((N, parent))
if isNull(R) then do
continue // So no new node add to this layer.
S.push((R, parent))
if marked(R) then do
continue
if isGoal(R) then do // If it's goal don't have to explore it.
return true
markVisited(R)
if depthMax((R, parent)) then do
continue
S.push((null, R))
return false
The problem I want to solve is a modification from it: it substitutes the stack S
with PriorityQueue PQ
. This algorithm is used to simulate IDA* algorithm (this is stated in a textbook, which unfortunately not written in English, so I won't provide reference / book title):
DFS2(N0, f, LIMIT):
PriorityQueueInit(PQ)
// A node (N, parent) stored in PQ represents a path from `N0` to `N`\
passing the node `parent`; A node with smaller value on f() is \
prioritized than those with larger value.
PQ.push((N0, null))
if isGoal(N0) then do
return true
markVisited(N0)
PQ.push((null, N0))
while !isEmpty(PQ) then do // (1)
(N, parent) := PQ.poll()
R := next((N, parent)) // (2)
if isNull(R) then do
continue
PQ.offer((R, parent))
if marked(R) then do
continue
if isGoal(R) then do
return true
markVisited(R)
if f((R, parent)) > LIMIT then do
continue
PQ.offer((null, R))
return false
S
is close list, so I assume that in the second pseudocode PQ
is close list, too. So how can the second pseudocode simulate IDA* algorithm, with a close list?PQ
, which is probably not a sibling of node N
, ie It jumps to another subtree from current subtree contains N
. What's the purpose of this line?updated for more information: I have spent many time and effort on this question, but it seems to be very hard because of the following points:
All graphs appear in the textbook are drawn tree-like, ie only one parent for each node, to show the concepts. This makes me confused: Does the second algorithm only work for trees?
Considering the line
if f((R, parent)) > LIMIT then do...
If the second one also works for graph, not just tree, then there might be many parents go to R
, should I consider all cases or just the current one, parent
?
There's a lot going on here.
As far as I can tell this code always returns the first goal node that reaches the top of the queue. Under the assumptions below about f and next, this goal node is f-optimal. But I wouldn't call this IDA*.
First, typically both A* and IDA* will open all neighbors of the current node at the same time. This code...doesn't. It uses iterators but only one loop. The first push is for the next sibling of the current node, and the second push is for the child. This is fine, I guess, except that siblings should be enumerated in increasing f-order so that a promising sibling doesn't get hidden after an unpromising one.
Second, unlike A*, IDA* doesn't have a close list. In a sense IDA* always has a search tree , since if it reaches two equivalent nodes, it still treats them as if they are distinct nodes. A* does have a close list, but it's more complicated than what's presented here. The way that A* handles cycles is that, if it discovers a cheaper path to an already closed node, then it reopens the node. This code doesn't, so it's only correct if there is never a need to reopen a node. As a result, this code needs f to be what's called a consistent heuristic (on every path, f never goes down as you follow the path), while A* only needs f to be admissible (f never underestimates the cost to reach a goal state).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.