问题
I have a problem with a rule match in Clips, in particular i can't understand why this rule doesn't actives.
(deffunction get-unknow-col (?col)
(bind ?facts (length (find-all-facts ((?a a-cell)) (and (eq ?a:y ?col) (eq ?a:content unk)))))
(return ?facts)
)
(deffunction get-boat-pieces-col (?col)
(bind ?facts (length (find-all-facts ((?a a-cell)) (and (eq ?a:y ?col) (and (neq ?a:content unk) (neq ?a:content water))))))
(return ?facts)
)
(defrule mark-remaining-unk-cells-col (declare (salience 40))
(k-per-col (col ?y) (num ?num))
(test (= (+ (get-unknow-col ?y) (get-boat-pieces-col ?y)) ?num))
=>
(do-for-all-facts ((?cell a-cell)) (and (eq ?cell:y ?y) (eq ?cell:content unk))
(modify ?cell (content boat-piece))
)
)
But in (facts) I have the correct values, in fact running:
(k-per-col (col 9) (num 1))
(get-unknow-col 9)
1
(get-boat-pieces-col 9)
0
CLIPS> (= (+ (get-unknow-col 9) (get-boat-pieces-col 9)) 1)
TRUE
The rule instead works only if num is 0 (correctly):
FIRE 75 mark-remaining-unk-cells-col: f-137
***** Y:8 num: 0 get-unknown-col: 0 get-boat-pieces-col 0
FIRE 76 mark-remaining-unk-cells-col: f-136
***** Y:7 num: 0 get-unknown-col: 0 get-boat-pieces-col 0
Why it doesnt activate when num=1, get-unknow-col=1, get-boat-pieces-col=0 and the test is true? Where i'm wrong?
回答1:
This is the relevant behavior description from the CLIPS Basic Programming Guide, Section 5.4.2 Test Conditional Element:
A test CE is evaluated when all proceeding CEs are satisfied. This means that a test CE will be evaluated more than once if the proceeding CEs can be satisfied by more than one group of pattern entities. In order to cause the reevaluation of a test CE, a pattern entity matching a CE prior to the test CE must be changed.
When the k-per-col fact is asserted the test CE will be evaluated. If this occurs before any or all a-cell facts have been asserted, then you will not get the same results as if you had asserted all of the a-cell facts first and then the k-per-col fact.
In order to insure predictable behavior, expressions evaluated by the test CE should always return the same value for a specific set of arguments. In this case, the get-unknow-col and get-boat-pieces-col functions can return different values even if the parameter ?col is the same as a previous call.
Some rule-based language provide a "collect" conditional element which allows to easily count the number of facts matching a pattern, but unfortunately CLIPS does not provide this. In order to add this functionality, you'd need to create facts and rules which track the values of interest.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate a-cell
(slot id (default-dynamic (gensym*)))
(slot x)
(slot y)
(slot content (allowed-values water left right middle top bot sub unk)))
CLIPS>
(deftemplate track-a-cell
(slot x (default any))
(slot y (default any))
(slot content (default any))
(multislot matches))
CLIPS>
(deffacts trackers
(track-a-cell (x any) (y 9) (content unk)))
CLIPS>
(defrule add-a-cell-match
(declare (salience 10))
?t <- (track-a-cell (x ?x1) (y ?y1) (content ?c1) (matches $?m))
(a-cell (id ?id) (x ?x2) (y ?y2) (content ?c2))
(test (and (not (member$ ?id ?m))
(or (eq ?x1 any) (eq ?x1 ?x2))
(or (eq ?y1 any) (eq ?y1 ?y2))
(or (eq ?c1 any) (eq ?c1 ?c2))))
=>
(modify ?t (matches ?m ?id)))
CLIPS>
(defrule remove-a-cell-match
(declare (salience 10))
?t <- (track-a-cell (x ?x1) (y ?y1) (content ?c1) (matches $?b ?id $?e))
(not (and (a-cell (id ?id) (x ?x2) (y ?y2) (content ?c2))
(test (and (or (eq ?x1 any) (eq ?x1 ?x2))
(or (eq ?y1 any) (eq ?y1 ?y2))
(or (eq ?c1 any) (eq ?c1 ?c2))))))
=>
(modify ?t (matches ?b ?e)))
CLIPS>
(deffacts init
(a-cell (x 0) (y 9) (content water))
(a-cell (x 1) (y 9) (content unk))
(a-cell (x 2) (y 9) (content water))
(a-cell (x 3) (y 9) (content water))
(a-cell (x 5) (y 9) (content water))
(a-cell (x 6) (y 9) (content unk))
(a-cell (x 7) (y 9) (content water))
(a-cell (x 8) (y 9) (content water))
(a-cell (x 9) (y 9) (content water))
(a-cell (x 4) (y 9) (content unk)))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-3 (a-cell (id gen2) (x 1) (y 9) (content unk))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-7 (a-cell (id gen6) (x 6) (y 9) (content unk))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-14 (track-a-cell (x any) (y 9) (content unk) (matches gen10 gen6 gen2))
For a total of 12 facts.
CLIPS> (retract 3 7)
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-16 (track-a-cell (x any) (y 9) (content unk) (matches gen10))
For a total of 10 facts.
CLIPS> (assert (a-cell (x 1) (y 9) (content unk)))
<Fact-17>
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-2 (a-cell (id gen1) (x 0) (y 9) (content water))
f-4 (a-cell (id gen3) (x 2) (y 9) (content water))
f-5 (a-cell (id gen4) (x 3) (y 9) (content water))
f-6 (a-cell (id gen5) (x 5) (y 9) (content water))
f-8 (a-cell (id gen7) (x 7) (y 9) (content water))
f-9 (a-cell (id gen8) (x 8) (y 9) (content water))
f-10 (a-cell (id gen9) (x 9) (y 9) (content water))
f-11 (a-cell (id gen10) (x 4) (y 9) (content unk))
f-17 (a-cell (id gen11) (x 1) (y 9) (content unk))
f-18 (track-a-cell (x any) (y 9) (content unk) (matches gen10 gen11))
For a total of 11 facts.
CLIPS>
来源:https://stackoverflow.com/questions/62075494/clips-rule-dont-match