CLIPS 区块世界

CLIPS blocks world

我正在尝试创建一个 CLIPS 程序,它将采用任何初始堆栈并将其重新排列到任何目标堆栈中。我断言这个,但它似乎没有做任何事情。

(assert (stack A B C) (stack D E F) (goal-stack D C B) (goal-stack A) (goal-stack F E))

到目前为止,这是我的代码:

(defrule move-direct
;(declare (salience 10000))
?stack1 <- (stack ?block1 $?bottom1)
?stack2 <- (stack ?block2 $?bottom2)
(goal-stack ?block1 ?block2 $?goalbottom)
=>
(retract ?stack1 ?stack2)
(assert (stack ?block1 ?block2 ?bottom2))
 (assert (stack $?bottom1))
 (printout t ?block1 " moved on top of " ?block2 crlf))

(defrule move-on-floor
; (declare (salience 10000))
 ?stack1 <- (stack ?top $?blocks ?movethisblock $?bottom1)
;(goal-stack ?movethisblock $?bottom1)
 (goal-stack $?blocks ?movethisblock $?bottom2)
 =>
 (retract ?stack1)
 (assert (stack ?top))
 (assert (stack $?blocks ?movethisblock $?bottom1))
 (printout t ?top " moved on to the floor" crlf))

调试代码通常涉及质疑您的期望。您希望 move-direct 和 move-on-floor 规则有所作为,但为什么呢?对于直接移动规则和您所做的断言,前两个模式中 ?block1 和 ?block2 的唯一可能值是 A 或 D。因此第三个模式必须匹配以 A A 开头的目标堆栈, A D, D A, or D D。这样的目标栈不存在,所以这条规则不匹配。

对于楼层移动规则,请查看每个案例。如果 (goal-stack A) 匹配目标堆栈模式,其中 ?move-this-block 是 A 并且 $?blocks 是 (),那么必须有一个堆栈在 A 顶部有一个块(变量 ?top)。由于 A 位于堆栈顶部,因此此目标堆栈不匹配规则。

如果 (goal-stack F E) 与 goal-stack 模式匹配,则序列 ($?blocks ?move-this-block) 是 (F E) 或 F。这些序列中的任何一个都不存在堆栈,其中顶部只有一个块,因此不会匹配此序列的规则。

如果(目标堆栈 D C B)匹配目标堆栈模式,则必须匹配堆栈的目标堆栈中的序列是(D C B)、(D C)或(D)。同样,没有包含此序列的堆栈,序列顶部只有一个块。

在直接移动规则的逻辑中,您只想在现有堆栈与目标堆栈的底部匹配时直接移动方块。对于在地板上移动的规则,您还需要确保您没有将块从部分完成的堆栈中移出。

              CLIPS (6.31 2/3/18)
    CLIPS> 
(defrule move-direct
   (declare (salience 10))
   ?stack1 <- (stack ?block1 $?bottom)
   ?stack2 <- (stack ?block2 $?goalbottom)
   (goal-stack $? ?block1 ?block2 $?goalbottom)
   =>
   (retract ?stack1 ?stack2)
   (assert (stack ?block1 ?block2 ?goalbottom))
   (assert (stack $?bottom))
   (printout t ?block1 " moved on top of " ?block2 crlf))
CLIPS> 
(defrule move-on-floor
   (goal-stack $? ?next $?goalbottom)
   (not (stack $? ?next $?goalbottom))
   ?stack <- (stack $?top ?bottom)
   (test (member$ ?next ?top))
   =>
   (retract ?stack)
   (assert (stack (nth$ 1 ?top)))
   (assert (stack (rest$ ?top) ?bottom))
   (printout t (nth$ 1 ?top) " moved on to the floor" crlf))
CLIPS> 
(assert (stack A B C)
        (stack D E F)
        (goal-stack D C B)
        (goal-stack A)
        (goal-stack F E))
<Fact-5>
CLIPS> (run)
D moved on to the floor
E moved on to the floor
F moved on top of E
A moved on to the floor
B moved on to the floor
C moved on top of B
D moved on top of C
CLIPS> (facts)
f-0     (initial-fact)
f-3     (goal-stack D C B)
f-4     (goal-stack A)
f-5     (goal-stack F E)
f-10    (stack F E)
f-11    (stack)
f-12    (stack A)
f-17    (stack D C B)
For a total of 8 facts.
CLIPS> (reset)
CLIPS> 
(assert (stack A B C)
        (goal-stack A B)
        (goal-stack C))
<Fact-3>
CLIPS> (run)
A moved on to the floor
B moved on to the floor
A moved on top of B
CLIPS> (facts)
f-0     (initial-fact)
f-2     (goal-stack A B)
f-3     (goal-stack C)
f-7     (stack C)
f-8     (stack A B)
f-9     (stack)
For a total of 6 facts.
CLIPS>