在 if 语句中使用 exists

Using exists in if statement

我正在尝试在 CLIPS 中实现生命游戏,但在尝试对每个单元格的邻居进行计数时遇到了存在语句的问题('exists' 缺少函数声明)。不能在 if 语句中使用 exists 语句吗?我应该如何处理计算邻居的任务?

这是单元格模板:

(deftemplate cell
    (slot iteration)
    (slot x)
    (slot y)
)

这是函数:

(deffunction countneighbors (?i ?j ?c)
    (bind ?*neighbors* 0)
    (if (exists (cell (iteration ?c) (x (- ?i 1)) (y (- ?j 1)))) then
        (bind ?*neighbors* (+ 0 1 ?*neighbors*))
    )
    (if (exists (cell (iteration ?c) (x (- ?i 1)) (y ?j))) then
        (bind ?*neighbors* (+ 0 1 ?*neighbors*))
    )
.
.
.
)

exists 条件元素不是一个函数,所以你不能像函数一样调用它。它只能在规则的条件下使用。如果您想在规则条件之外迭代一组事实,您可以使用事实查询函数:

         CLIPS (6.31 2/3/18)
CLIPS> 
(deftemplate cell
   (slot iteration (default 0))
   (slot x)
   (slot y))
CLIPS> 
(deffacts cells
   (cell (x 1) (y 1))  
   (cell (x 1) (y 2))  ;;; - * *
   (cell (x 2) (y 3))  ;;; * - -
   (cell (x 3) (y 3))) ;;; * - -
CLIPS>    
(deffunction count-neighbors (?i ?j ?c)
   (bind ?neighbors 0)
   (do-for-all-facts ((?cell cell)) 
                     (and (= ?cell:iteration ?c)
                          (<= (abs (- ?i ?cell:x)) 1)
                          (<= (abs (- ?j ?cell:y)) 1)
                          (or (!= ?i ?cell:x) (!= ?j ?cell:y)))
      (bind ?neighbors (+ 1 ?neighbors)))
   ?neighbors)

CLIPS> (reset)
CLIPS> (count-neighbors 1 1 0)
1
CLIPS> (count-neighbors 2 2 0)
4
CLIPS> (count-neighbors 2 1 0)
2
CLIPS> 

这是使用规则确定邻居的技巧:

CLIPS> (clear)
CLIPS> 
(deftemplate cell
   (slot iteration (default 0))
   (slot x)
   (slot y)
   (slot alive (default 0))
   (multislot neighbors))
CLIPS>    
(deftemplate direction
   (slot d)
   (slot dx)
   (slot dy))
CLIPS> 
(deffacts cells
   (cell (x 1) (y 1) (alive 1))  
   (cell (x 1) (y 2) (alive 1))
   (cell (x 1) (y 3))
   (cell (x 2) (y 1))
   (cell (x 2) (y 2))  
   (cell (x 2) (y 3) (alive 1))
   (cell (x 3) (y 1))
   (cell (x 3) (y 2))  
   (cell (x 3) (y 3) (alive 1)))
CLIPS> 
(deffacts directions
   (direction (d n)  (dx 0)  (dy 1))
   (direction (d ne) (dx 1)  (dy 1))
   (direction (d e)  (dx 1)  (dy 0))
   (direction (d se) (dx 1)  (dy -1))
   (direction (d s)  (dx 0)  (dy -1))
   (direction (d sw) (dx -1) (dy -1))
   (direction (d w)  (dx -1) (dy 0))
   (direction (d nw) (dx -1) (dy 1))) 
CLIPS>               
(defrule add-neighbor
   ?c <- (cell (x ?x) (y ?y) (neighbors $?n))
   (direction (d ?d) (dx ?dx) (dy ?dy))
   (cell (x =(+ ?x ?dx)) (y =(+ ?y ?dy)) (alive 1))
   (test (not (member$ ?d ?n)))
   =>
   (modify ?c (neighbors $?n ?d))) 
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-7     (cell (iteration 0) (x 3) (y 1) (alive 0) (neighbors))
f-10    (direction (d n) (dx 0) (dy 1))
f-11    (direction (d ne) (dx 1) (dy 1))
f-12    (direction (d e) (dx 1) (dy 0))
f-13    (direction (d se) (dx 1) (dy -1))
f-14    (direction (d s) (dx 0) (dy -1))
f-15    (direction (d sw) (dx -1) (dy -1))
f-16    (direction (d w) (dx -1) (dy 0))
f-17    (direction (d nw) (dx -1) (dy 1))
f-19    (cell (iteration 0) (x 2) (y 1) (alive 0) (neighbors nw w))
f-21    (cell (iteration 0) (x 3) (y 2) (alive 0) (neighbors nw n))
f-25    (cell (iteration 0) (x 2) (y 2) (alive 0) (neighbors w sw ne n))
f-26    (cell (iteration 0) (x 3) (y 3) (alive 1) (neighbors w))
f-28    (cell (iteration 0) (x 2) (y 3) (alive 1) (neighbors e sw))
f-30    (cell (iteration 0) (x 1) (y 2) (alive 1) (neighbors ne s))
f-31    (cell (iteration 0) (x 1) (y 1) (alive 1) (neighbors n))
f-33    (cell (iteration 0) (x 1) (y 3) (alive 0) (neighbors s e))
For a total of 18 facts.
CLIPS> 

这是一个完整的实现,它只保留代表活细胞的事实。

(deffacts start-phase
   (phase neighbors))

(deftemplate cell
   (slot x)
   (slot y)
   (slot alive (default no))
   (multislot neighbors))

(deffacts glider
   (cell (x 1) (y 2) (alive yes))
   (cell (x 2) (y 3) (alive yes))
   (cell (x 3) (y 1) (alive yes))
   (cell (x 3) (y 2) (alive yes))
   (cell (x 3) (y 3) (alive yes)))

(deftemplate direction
   (slot tag)
   (slot dx (default 0))
   (slot dy (default 0)))

(deffacts directions
   (direction (tag n) (dy 1))
   (direction (tag ne) (dx 1) (dy 1))
   (direction (tag e) (dx 1))
   (direction (tag se) (dx 1) (dy -1))
   (direction (tag s) (dy -1))
   (direction (tag sw) (dx -1) (dy -1))
   (direction (tag w) (dx -1))
   (direction (tag nw) (dx -1) (dy 1)))

(defrule check-for-life
   (phase neighbors)
   (cell (x ?x) (y ?y) (alive yes))
   (direction (tag ?tag) (dx ?dx) (dy ?dy))
   (not (cell (x =(+ ?x ?dx)) (y =(+ ?y ?dy))))
   =>
   (assert (cell (x (+ ?x ?dx)) (y (+ ?y ?dy)))))

(defrule add-neighbor
   (phase neighbors)
   ?c <- (cell (x ?x) (y ?y) (neighbors $?n))
   (direction (tag ?t) (dx ?dx) (dy ?dy))
   (cell (x =(+ ?x ?dx)) (y =(+ ?y ?dy)) (alive yes))
   (test (not (member$ ?t ?n)))
   =>
   (modify ?c (neighbors ?t ?n)))

(defrule remove-neighbor
   (phase neighbors)
   ?c <- (cell (x ?x) (y ?y) (neighbors $?b ?t $?e))
   (direction (tag ?t) (dx ?dx) (dy ?dy))
   (not (cell (x =(+ ?x ?dx)) (y =(+ ?y ?dy)) (alive yes)))
   =>
   (modify ?c (neighbors ?b ?e)))

(defrule life-to-death
   (phase life)
   ?c <- (cell (alive yes) (neighbors $?n))
   (test (not (= (length$ ?n) 2)))
   (test (not (= (length$ ?n) 3)))
   =>
   (retract ?c)) 

(defrule death-to-life
   (phase life)
   ?c <- (cell (alive no) (neighbors $?n))
   (test (= (length$ ?n) 3))
   =>
   (modify ?c (alive yes))) 

(defrule death-to-death
   (phase life)
   ?c <- (cell (alive no) (neighbors $?n))
   (test (!= (length$ ?n) 3))
   =>
   (retract ?c)) 

(defrule neighbors-to-life
   (declare (salience -10))
   ?p <- (phase neighbors)
   =>
   (retract ?p)
   (assert (phase life)))

(defrule life-to-neighbors
   (declare (salience -10))
   ?p <- (phase life)
   =>
   (retract ?p)
   (assert (phase neighbors)))