Search code examples
clips

CLIPS blocks world


I am trying to create a CLIPS program that will take any initial stack and rearrange it into any goal-stack. I am asserting this, but it doesn't seem to do anything.

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

This is my code so far:

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

Solution

  • Debugging code usually involves questioning your expectations. You expect the move-direct and move-on-floor rules to do something, but why? For the move-direct rule and the assertions you've made, the only possible values for ?block1 and ?block2 in the first two patterns are either A or D. So the third pattern must match a goal-stack that starts with either A A, A D, D A, or D D. Such a goal-stack does not exist, so this rule is unmatched.

    For the move-on-floor rule, look at each case. If (goal-stack A) matches the goal-stack pattern where ?move-this-block is A and $?blocks is (), then there must be stack that has a block on top of A (the variable ?top). Since A is at the top of the stack, the rule won't be matched for this goal-stack.

    if (goal-stack F E) matches the goal-stack pattern, the sequence ($?blocks ?move-this-block) is either (F E) or F. There is no stack with either of these sequences where there's just a single block on top, so the rule won't be matched for this sequence.

    If (goal-stack D C B) matches the goal-stack pattern the sequence from the goal-stack that must match the stack is either (D C B), (D C) or (D). Again there's no stack that contains this sequence with just a single block on top of the sequence.

    In the logic for the move-direct rule, you only want to directly move the block when the existing stack matches the bottom portion of a goal-stack. For the move-on-floor rule you also want to insure that you're not moving blocks off a partially completed stack.

                  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>