好的,我有一个BFS的Lisp实现,我正在尝试转换它来进行爬山搜索。
下面是我的BFS代码:
; The list of lists is the queue that we pass BFS. the first entry and
; every other entry in the queue is a list. BFS uses each of these lists and
; the path to search.
(defun shortest-path (start end net)
(BFS end (list (list start)) net))
;We pass BFS the end node, a queue containing the starting node and the graph
;being searched(net)
(defun BFS (end queue net)
(if (null queue) ;if the queue is empty BFS has not found a path so exit
nil
(expand-queue end (car queue) (cdr queue) net)))
(defun expand-queue (end path queue net)
(let ((node (car path)))
(if (eql node end) ; If the current node is the goal node then flip the path
; and return that as the answer
(reverse path)
; otherwise preform a new BFS search by appending the rest of
; the current queue to the result of the new-paths function
(BFS end (append queue (new-paths path node net)) net))))
; mapcar is called once for each member of the list new-paths is passed
; the results of this are collected into a list
(defun new-paths (path node net)
(mapcar #'(lambda (n) (cons n path))
(cdr (assoc node net))))
现在,我知道我不需要像在BFS中那样一直扩展左节点,而是需要扩展看起来最接近目标状态的节点。
我使用的图表如下:
(a (b 3) (c 1))
(b (a 3) (d 1))
我有一个转换函数来实现上述的BFS实现,但是现在我需要使用这个图形格式将其转换为爬山。
我只是不知道从哪里开始,一直在尝试没有结果的事情我知道我主要需要更改
expand-queue
函数来展开最近的节点,但我似乎无法创建一个函数来确定哪个节点最接近。谢谢你的帮助!
最佳答案
把事情附加到列表的末尾是错误的这是最昂贵的行动与名单。
复制整个列表,然后附加另一个列表。在递归过程中使用它,这意味着每次展开节点以创建新路径时都会执行此操作。
如果将项目放入队列,则需要查看执行此操作的顺序在广度优先的情况下,一个节点访问一个级别中的每个节点,然后移动到下一个级别爬山需要你用一个加权函数对候选人进行“最佳”排序所以需要某种函数来计算当前节点和下一个候选节点的数值然后需要对候选节点进行排序,并首先展开“最佳”节点对于后进先出(last-in,first-out)队列,这意味着最有前途的节点需要被推到最后,这样它将是第一个被扩展的节点。请注意,后进先出队列非常适合单独链接的列表先进先出(FIFO)不是。
计算机科学的一个典型概念是数据抽象如果后进先出队列是这样一种数据结构,则需要定义MAKE-LIFO-QUEUE、EMPTY-QUEUE-P等函数然后,您将使用这些函数而不是LIST、NULL和其他函数,它们使数据结构的用途更加清晰这会使您的代码更长,但是由于Lisp列表是通用的,并且可以(ab-)用于各种使用场景,因此单看列表操作并不能说明它们的意图对于更复杂的图算法,这一点尤为重要。
关于search - Lisp-爬山,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5833471/