Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Search 如何减少8字谜A*搜索中的长执行时间_Search_Lisp_Common Lisp_Heuristics_Sliding Tile Puzzle - Fatal编程技术网

Search 如何减少8字谜A*搜索中的长执行时间

Search 如何减少8字谜A*搜索中的长执行时间,search,lisp,common-lisp,heuristics,sliding-tile-puzzle,Search,Lisp,Common Lisp,Heuristics,Sliding Tile Puzzle,我正在尝试对Lisp中的“8字谜”实施启发式搜索策略A* 要运行搜索,请使用以下命令: (01 2 3 4 5 6 B 7)(01 2 3 4 5 6 7 B) 其中第一个状态是开始目标,第二个状态是结束目标 然而,我的程序运行了很长一段时间。最后,我假设它将堆栈溢出*编辑:它不会耗尽内存,但是它花了30分钟,比我的广度优先搜索要长得多 搜索算法代码: ;;; This is one of the example programs from the textbook: ;;; ;;; Artif

我正在尝试对Lisp中的“8字谜”实施启发式搜索策略A*

要运行搜索,请使用以下命令: (01 2 3 4 5 6 B 7)(01 2 3 4 5 6 7 B)

其中第一个状态是开始目标,第二个状态是结束目标

然而,我的程序运行了很长一段时间。最后,我假设它将堆栈溢出*编辑:它不会耗尽内存,但是它花了30分钟,比我的广度优先搜索要长得多

搜索算法代码:

;;; This is one of the example programs from the textbook:
;;;
;;; Artificial Intelligence: 
;;; Structures and strategies for complex problem solving
;;;
;;; by George F. Luger and William A. Stubblefield
;;;
;;; Corrections by Christopher E. Davis (chris2d@cs.unm.edu)
;;; insert-by-weight will add new child states to an ordered list of 
;;; states-to-try.  
(defun insert-by-weight (children sorted-list)
  (cond ((null children) sorted-list)
        (t (insert (car children) 
           (insert-by-weight (cdr children) sorted-list)))))

(defun insert (item sorted-list)
  (cond ((null sorted-list) (list item))
        ((< (get-weight item) (get-weight (car sorted-list)))
         (cons item sorted-list))
        (t (cons (car sorted-list) (insert item (cdr sorted-list))))))


;;; run-best is a simple top-level "calling" function to run best-first-search

(defun run-best (start goal)
  (declare (special *goal*)
           (special *open*)
           (special *closed*))
  (setq *goal* goal)
  (setq *open* (list (build-record start nil 0 (heuristic start))))
  (setq *closed* nil)
  (best-first))

;;; These functions handle the creation and access of (state parent) 
;;; pairs.

(defun build-record (state parent depth weight) 
  (list state parent depth weight))

(defun get-state (state-tuple) (nth 0 state-tuple))

(defun get-parent (state-tuple) (nth 1 state-tuple))

(defun get-depth (state-tuple) (nth 2 state-tuple))

(defun get-weight (state-tuple) (nth 3 state-tuple))

(defun retrieve-by-state (state list)
  (cond ((null list) nil)
        ((equal state (get-state (car list))) (car list))
        (t (retrieve-by-state state (cdr list)))))


;; best-first defines the actual best-first search algorithm
;;; it uses "global" open and closed lists.

(defun best-first ()
  (declare (special *goal*)
           (special *open*)
           (special *closed*)
           (special *moves*))
  (print "open =") (print *open*)
  (print "closed =") (print *closed*)
  (cond ((null *open*) nil)
        (t (let ((state (car *open*)))
             (setq *closed* (cons state *closed*))
             (cond ((equal (get-state state) *goal*) (reverse (build-solution *goal*)))
                   (t (setq *open* 
                            (insert-by-weight 
                                    (generate-descendants (get-state state)
                                                          (1+ (get-depth state))
                                                          *moves*)
                                    (cdr *open*)))
                      (best-first)))))))


;;; generate-descendants produces all the descendants of a state

(defun generate-descendants (state depth moves)
  (declare (special *closed*)
           (special *open*))
  (cond ((null moves) nil)
        (t (let ((child (funcall (car moves) state))
                 (rest (generate-descendants state depth (cdr moves))))
             (cond ((null child) rest)
                   ((retrieve-by-state child rest) rest)
                   ((retrieve-by-state child *open*) rest)
                   ((retrieve-by-state child *closed*) rest)
                   (t (cons (build-record child state depth 
                                          (+ depth (heuristic child))) 
                            rest)))))))


(defun build-solution (state)
  (declare (special *closed*))
  (cond ((null state) nil)
        (t (cons state (build-solution 
                        (get-parent 
                         (retrieve-by-state state *closed*)))))))

尝试memoize实用程序。您可以在此处找到相关问题()。 Memoize跟踪对任何memoized函数的调用,并立即返回任何已知(以前计算过的)结果,以避免重新计算它们。对于像您这样的递归函数,结果是惊人的。

代码中的问题:

  • 递归。写循环以避免堆栈溢出

  • 可能是长的打开和关闭列表。打开和关闭的列表可能相当长。一个操作是检查列表上是否有具有特定状态的记录。我将使用哈希表记录状态,然后使用该表检查状态是否存在

我的代码版本

无解决方案:

CL-USER 220 > (time (run-best '(0 1 2 3 4 5 6 7 8)
                              '(0 2 1 3 4 5 6 7 8)
                              '(right1 left1 up down)))
Timing the evaluation of (RUN-BEST (QUOTE (0 1 2 3 4 5 6 7 8))
                                   (QUOTE (0 2 1 3 4 5 6 7 8))
                                   (QUOTE (RIGHT1 LEFT1 UP DOWN)))

User time    =  0:01:05.620
System time  =        0.220
Elapsed time =  0:01:05.749
Allocation   = 115386560 bytes
22397 Page faults
NO-SOLUTION
解决方案:

CL-USER 223 > (time (pprint (run-best '(2 1 5 3 4 6 0 8 7)
                                      '(0 1 2 3 4 5 6 7 8)
                                      '(right1 left1 up down))))
Timing the evaluation of (PPRINT (RUN-BEST (QUOTE (2 1 5 3 4 6 0 8 7))
                                           (QUOTE (0 1 2 3 4 5 6 7 8))
                                           (QUOTE (RIGHT1 LEFT1 UP DOWN))))

((2 1 5 3 4 6 0 8 7)
 (2 1 5 0 4 6 3 8 7)
 (2 1 5 4 0 6 3 8 7)
 (2 0 5 4 1 6 3 8 7)
 (0 2 5 4 1 6 3 8 7)
 (4 2 5 0 1 6 3 8 7)
 (4 2 5 1 0 6 3 8 7)
 (4 2 5 1 6 0 3 8 7)
 (4 2 5 1 6 7 3 8 0)
 (4 2 5 1 6 7 3 0 8)
 (4 2 5 1 0 7 3 6 8)
 (4 2 5 1 7 0 3 6 8)
 (4 2 0 1 7 5 3 6 8)
 (4 0 2 1 7 5 3 6 8)
 (0 4 2 1 7 5 3 6 8)
 (1 4 2 0 7 5 3 6 8)
 (1 4 2 3 7 5 0 6 8)
 (1 4 2 3 7 5 6 0 8)
 (1 4 2 3 0 5 6 7 8)
 (1 0 2 3 4 5 6 7 8)
 (0 1 2 3 4 5 6 7 8))
User time    =        0.115
System time  =        0.001
Elapsed time =        0.103
Allocation   = 2439744 bytes
194 Page faults

旁注:使用
defstruct
defclass
而不是状态列表我将删除各种递归并使用普通迭代。另请参见合并和查找…
(defstruct srecord state parent depth weight)
@Asiax3使用Rainer Joswig提供的代码,已经为您生成了访问器。您不需要编写所有的
get-*
函数。此外,您还可以使用
(make srecord:states s…
)创建新状态。还有像
(setf(srecord parent state)p)
这样的setf函数也被定义了,尽管您似乎没有改变插槽。这将简化您的代码。但代码的优点在于,您提供了一个功能接口,比在使用特定插槽的任何地方编写
(n…
都要好。不是每个人都这么做。嗨,利奥,我试图利用记忆工具,但我一定是记住了错误的功能。我试着在函数“herusitic eval”和“best first”中使用它。你不会相信的。。。我使用了错误的开始和目标状态。。!我用的是(0 1,2,3,4,5,6,7,B),表示B是空白,而不是0。就在看到这个评论之后。现在我也成功地实现了defstruct,一切都很顺利D
CL-USER 223 > (time (pprint (run-best '(2 1 5 3 4 6 0 8 7)
                                      '(0 1 2 3 4 5 6 7 8)
                                      '(right1 left1 up down))))
Timing the evaluation of (PPRINT (RUN-BEST (QUOTE (2 1 5 3 4 6 0 8 7))
                                           (QUOTE (0 1 2 3 4 5 6 7 8))
                                           (QUOTE (RIGHT1 LEFT1 UP DOWN))))

((2 1 5 3 4 6 0 8 7)
 (2 1 5 0 4 6 3 8 7)
 (2 1 5 4 0 6 3 8 7)
 (2 0 5 4 1 6 3 8 7)
 (0 2 5 4 1 6 3 8 7)
 (4 2 5 0 1 6 3 8 7)
 (4 2 5 1 0 6 3 8 7)
 (4 2 5 1 6 0 3 8 7)
 (4 2 5 1 6 7 3 8 0)
 (4 2 5 1 6 7 3 0 8)
 (4 2 5 1 0 7 3 6 8)
 (4 2 5 1 7 0 3 6 8)
 (4 2 0 1 7 5 3 6 8)
 (4 0 2 1 7 5 3 6 8)
 (0 4 2 1 7 5 3 6 8)
 (1 4 2 0 7 5 3 6 8)
 (1 4 2 3 7 5 0 6 8)
 (1 4 2 3 7 5 6 0 8)
 (1 4 2 3 0 5 6 7 8)
 (1 0 2 3 4 5 6 7 8)
 (0 1 2 3 4 5 6 7 8))
User time    =        0.115
System time  =        0.001
Elapsed time =        0.103
Allocation   = 2439744 bytes
194 Page faults