我尝试使用维基百科中的伪代码编码Alpha-beta。程序到达(EQ depth 0)
后,它返回启发式值,但深度继续解除干扰,从而导致循环。现在我的代码看起来像这样:
(defun ab(tab node depth a b)
(cond ((EQ depth 0) (calculaH tab))
((eq (mod depth 2) 0) (setq v -999999) (setq movimiento (sigMov depth node tab)) (loop while (not(null movimiento))
do (setq v (max v (ab (nth 3 movimiento) movimiento (- depth 1) a b)))
(setq a (max a v))
(cond((<= b a) (break))
(t (setq movimiento (sigMov depth movimiento tab))))) (return v))
(t (setq v 999999) (setq movimiento (sigMov depth node tab)) (loop while (not(null movimiento))
do (setq v (min v (ab (nth 3 movimiento) movimiento (- depth 1) a b)))
(setq a (min b v))
(cond((<= b a) (break))
(t (setq movimiento (sigMov depth movimiento tab))))) (return v))))
我应该在代码中增加深度值吗?为什么递归本身不会增加值?
答案 0 :(得分:3)
维基百科上的alpha-beta prunning algorithm几乎可以按原样翻译成Lisp。由于它使用无限值,所以我们不要使用“999999”,而是定义min
和max
函数,这些函数可以使用这些特殊值可靠地运行:
(defpackage :alphabeta
(:use :cl)
;; custom min/max functions that support infinity
(:shadow min max))
(in-package :alphabeta)
(defvar -∞ '-∞ "Negative infinity symbol")
(defvar +∞ '+∞ "Positive infinity symbol")
(defun min (a b)
(cond
((eql a +∞) b)
((eql b +∞) a)
((eql a -∞) -∞)
((eql b -∞) -∞)
(t (cl:min a b))))
(defun max (a b)
(cond
((eql a -∞) b)
((eql b -∞) a)
((eql a +∞) +∞)
((eql b +∞) +∞)
(t (cl:max a b))))
代码还依赖于辅助功能,我在此声明这些功能以避免警告:
;; You need to implement the followning functions
(declaim (ftype function terminal-node-p heuristic-value children))
然后,伪代码几乎可以相同地写入。为了这个问题,我保留了相同的希腊变量,但正如Dan Robertson在评论中指出的那样,这可能会带来惊喜:
使用像α或β这样的名称时要注意的一件事是,典型的支持Unicode的lisp实现会将它们改为Α和Β。你能说出A和Α或B和Β之间的区别吗?
(defun alphabeta (node depth α β maximizing-player-p)
(when (or (= depth 0) (terminal-node-p node))
(return-from alphabeta (heuristic-value node)))
(if maximizing-player-p
(let ((value -∞))
(dolist (child (children node))
(setf value (max value (alphabeta child (1- depth) α β nil)))
(setf α (max α value))
(when (<= β α)
;; β cut-off
(return)))
value)
(let ((value +∞))
(dolist (child (children node))
(setf value (min value (alphabeta child (1- depth) α β t)))
(setf α (min α value))
(when (<= β α)
;; α cut-off
(return)))
value)))