- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试对 Lisp 中的“8-puzzle”谜题实现启发式搜索策略 A*。
要运行我的搜索,我使用命令:(最佳运行'(0 1 2 3 4 5 6 B 7)'(0 1 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*)))))))
8puzzle 的启发式函数:
(defun hole (grid)
"Return integer index into GRID at which the 'hole' is located."
(position '0 grid))
(defun col (pair)
(car pair))
(defun row (pair)
(cdr pair))
(defun coords (index1)
"Transform INDEX, an integer index into the list, into an (X . Y)
coordinate pair for a 3x3 grid."
(cons (second (multiple-value-list (floor index1 3)))
(floor index1 3)))
(defun index1 (coords)
"Transform COORDS, an (X . Y) coordinate pair for a 3x3 grid, into
an integer index."
(+ (col coords)
(* 3 (row coords))))
(defun swap (a b list)
"Return a new list equivalent to LIST but with the items at indexes
A and B swapped."
(let ((new (copy-seq list)))
(setf (nth a new)
(nth b list))
(setf (nth b new)
(nth a list))
new))
(defun right1 (grid)
"Move the 'hole' on the 3x3 GRID one space to the right. If there
is no space to the right, return NIL."
(let ((hole (coords (hole grid))))
(if (= 2 (col hole))
nil
(swap (index1 hole)
(index1 (cons (1+ (col hole)) (row hole)))
grid))))
(defun left1 (grid)
"Move the 'hole' on the 3x3 GRID one space to the left. If there
is no space to the left, return NIL."
(let ((hole (coords (hole grid))))
(if (zerop (col hole))
nil
(swap (index1 hole)
(index1 (cons (1- (col hole)) (row hole)))
grid))))
(defun up (grid)
"Move the 'hole' on the 3x3 GRID one space up. If there is no space
up, return NIL."
(let ((hole (coords (hole grid))))
(if (zerop (row hole))
nil
(swap (index1 (cons (col hole) (1- (row hole))))
(index1 hole)
grid))))
(defun down (grid)
"Move the 'hole' on the 3x3 GRID one space down. If there is no
space down, return NIL."
(let ((hole (coords (hole grid))))
(if (= 2 (row hole))
nil
(swap (index1 (cons (col hole) (1+ (row hole))))
(index1 hole)
grid))))
;Moves
(setq *moves*
'(right1 left1 up down))
;heuristics for puzzle8
(defun heuristic (state)
(declare (special *goal*))
(heuristic-eval state *goal*))
(defun heuristic-eval (state goal)
(cond ((null state) 0)
((equal (car state) (car goal))
(heuristic-eval (cdr state) (cdr goal)))
(t (1+ (heuristic-eval (cdr state) (cdr goal))))))
最佳答案
代码中的问题:
递归。编写循环以避免堆栈溢出
可能是长开放和封闭列表。打开和关闭列表可能会很长。一种操作是检查列表中是否存在具有特定状态的记录。我会使用哈希表来记录状态,然后使用该表来检查状态是否存在。
我的代码版本
无解:
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
关于search - 如何减少 A* 搜索 8-puzzle 中的长时间执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33206766/
我有一个独立的 Thread 应用程序。这是一个等待消息的监听器,当消息到达时执行一些操作,其中我必须将消息保存在数据库中。但我遇到了问题,因为如果我运行应用程序并“手动发送消息”,一切都会正常工作,
我有以下php代码: sleep(65); $query = "UPDATE database.table SET XXXXXXX = XXXXXXX - ".$YYYYYY." WHERE
我正在开发一个业余爱好应用程序。它在主布局中使用 webview。单击 webview 内的链接会使用户保持在 webview 内。启动后一切正常,但仍在应用程序内。但是,在手机休眠一段时间后,我重新
我目前运行的应用程序需要最大堆大小为 16GB。 目前我使用以下标志来处理垃圾回收。 -XX\:+UseParNewGC, -XX\:+UseConcMarkSweepGC, -XX:CMSIniti
$ uname -a Darwin Wheelie-Cyberman 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011
在 while 循环仍在休眠时退出它的最简单方法是什么?是否有某种函数可以在 sleep 时检测某个值是否为真? 或者我是否在循环中设置一个小 sleep 并检查如果不再睡一会儿就退出?如果可以,我该
我正在 Ubunu 的 Jetty 6 上运行 Java Web 服务器,用于基于反向 ajax 的 Web。而且我在向浏览器重新发送数据的线程滞后方面遇到了严重的问题。很多时候,一些线程开始 hib
当我运行长时间操作时,我遇到来自 IIS 的请求超时。我的 ASP.NET 应用程序正在后台处理数据,但处理的记录数量很大,因此操作需要很长时间。 但是,我认为 IIS 使 session 超时。这是
我不确定从哪里开始解决这个问题,但如果我有一个 AJAX 网络应用程序向服务器发送请求并在数据库(在我的例子中是 postgresql)上运行长查询,有没有办法停止或如果仍在运行时用户刷新页面或关闭
我是一名优秀的程序员,十分优秀!