在if语句中使用存在

时间:2019-03-29 16:12:16

标签: clips conways-game-of-life

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

这是单元格模板:

(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*))
    )
.
.
.
)

1 个答案:

答案 0 :(得分:1)

存在的条件元素不是函数,因此不能像一个函数那样调用它。它只能在规则条件下使用。如果要迭代规则条件之外的一组事实,可以使用事实查询功能:

         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)))