I wrote a program which asserts the facts in the LHS of this rule:
(defrule check-open-better (declare (salience 50))
?f1 <- (newnode (ident ?id) (gcost ?g) (fcost ?f) (father ?anc))
(status (ident ?id) (subject ?subject) (data $?eqL))
?f2 <- (status (ident ?old) (subject ?subject) (data $?eqL))
?f3 <- (node (ident ?old) (gcost ?g-old) (open yes))
(test
(eq
(implode$
(find-all-facts ((?f status))
(and
(eq(str-compare ?f:ident ?id) 0)
(eq(str-compare ?f:subject ?subject) 0)
(eq(str-compare (implode$ ?f:data) (implode$ $?eqL)) 0)
)
)
)
(implode$
(find-all-facts ((?f status))
(and
(eq(str-compare ?f:ident ?old) 0)
(eq(str-compare ?f:subject ?subject) 0)
(eq(str-compare (implode$ ?f:data) (implode$ $?eqL)) 0)
)
)
)
0)
)
(test (< ?g ?g-old))
?f4 <- (open-better ?a)
=>
(assert (node (ident ?id) (gcost ?g) (fcost ?f) (father ?anc) (open yes)))
(assert (open-better (+ ?a 1)))
(retract ?f1 ?f2 ?f3 ?f4)
(pop-focus)
(pop-focus))
node, newnode and status are defined as deftemplate.
When this rule is in the agenda, CLIPS crash like it was typed the (exit) command.
I'm sure it's not fault of the rules that assert facts that allow this rule to be added in the agenda. Does anyone know why?
If CLIPS is crashing, it's a bug in CLIPS. I tried reproducing the problem by filling in the missing pieces and running in CLIPS 6.3, 6.31, and 6.4, but was unable to get a crash.
(deftemplate newnode
(slot ident)
(slot gcost (type INTEGER))
(slot fcost)
(slot father))
(deftemplate status
(slot ident)
(slot subject)
(multislot data))
(deftemplate node
(slot ident)
(slot gcost (type INTEGER))
(slot open))
(deffacts start
(node (ident "1") (gcost 10) (open yes))
(open-better 0)
(newnode (ident "2"))
(status (ident "1"))
(status (ident "2")))
Generally, it's a bad idea to use the query functions from the conditions of a rule because 1) you can use pattern matching and 2) the query contained within a test CE will not be reevaluated unless there's some changes to prior patterns.
It's not clear what you're trying to do with the find-all-facts calls. First, there's cruft in there that you don't need. The str-compare and implode$ function calls are unnecessary and the third argument of 0 to eq will cause the test CE to always fail since the return values of the find-all-facts calls will never be 0.
(test
(eq
(find-all-facts ((?f status))
(and
(eq ?f:ident ?id)
(eq ?f:subject ?subject)
(eq ?f:data $?eqL)
)
)
(find-all-facts ((?f status))
(and
(eq ?f:ident ?old)
(eq ?f:subject ?subject)
(eq ?f:data $?eqL)
)
)
)
)
Both find-all-fact calls must return the same facts in order for the test CE to be satisfied. That can only be true if there are no status facts or the ?id and ?old variables have the same value.
Try this one, it should work. :)
(defrule check-open-better (declare (salience 50))
?f1 <- (newnode (ident ?id) (gcost ?g) (fcost ?f) (father ?anc))
(status (ident ?id) (subject ?subject) (data $?eqL))
?f2 <- (status (ident ?old) (subject ?subject) (data $?eqL))
?f3 <- (node (ident ?old) (gcost ?g-old) (open yes))
(test (< ?g ?g-old))
?f4 <- (open-better ?a)
=>
(if (eq
(implode$
(find-all-facts ((?f status))
(and
(eq ?f:ident ?id)
(eq ?f:subject ?subject)
(eq (implode$ ?f:data) (implode$ $?eqL)))))
(implode$
(find-all-facts ((?f status))
(and
(eq ?f:ident ?old)
(eq ?f:subject ?subject)
(eq (implode$ ?f:data) (implode$ $?eqL)) 0))))
then
(assert (node (ident ?id) (gcost ?g) (fcost ?f) (father ?anc) (open yes)))
(assert (open-better (+ ?a 1)))
(retract ?f1 ?f2 ?f3 ?f4))
(pop-focus)
(pop-focus))
Related
I'm trying to find the most common element across multiple multislot entry of type symbol and I don't seem to get a decent way to extracts the content of those multislot to single entry to iterate over.
==================================
(deftemplate chain ""
(multislot edge
(type SYMBOL))
)
(assert (chain (edge a b c d e f g)))
(assert (chain (edge d e f g h k l)))
(assert (chain (edge e o p q r s f)))
(deffunction find_most_common_edge ()
(bind ?edge (create$))
(bind ?counted_edge (create$))
(bind ?largest_count 0)
(do-for-all-facts ((?s chain)) TRUE
(loop-for-count (length$ ?s:edge) (?s1 (expand$ ?s:edge))
(if (not (member$ ?s1 ?counted_edge))
then
(bind ?counted_edge (create$ ?s1 ?counted_edge))
(bind ?count (length$ (find-all-facts ((?s2 chain)) (member$ ?s1 ?s2:edge))))
(if (= ?count ?largest_count)
then
(bind ?edge (create$ ?s1 ?edge))
else
(if (> ?count ?largest_count)
then
(bind ?largest_count ?count)
(bind ?edge (create$ ?s1)))))))
(return ?edge))
Using functions:
CLIPS (6.4 2/9/21)
CLIPS>
(deftemplate chain
(multislot edge (type SYMBOL)))
CLIPS>
(deffacts start
(chain (edge a b c d e f g))
(chain (edge d e f g h k l))
(chain (edge e o p q r s f)))
CLIPS>
(deffunction get-all-edges ()
(bind ?all-edges (create$))
(do-for-all-facts ((?f chain)) TRUE
(bind ?all-edges (create$ ?all-edges ?f:edge)))
(return ?all-edges))
CLIPS>
(deffunction count-edge (?e ?all-edges)
(bind ?all-length (length$ ?all-edges))
(return (- ?all-length (length$ (delete-member$ ?all-edges ?e)))))
CLIPS>
(deffunction remove-duplicates ($?mf)
(bind ?rv (create$))
(foreach ?v ?mf
(if (not (member$ ?v ?rv))
then
(bind ?rv (create$ ?rv ?v))))
(return ?rv))
CLIPS>
(deffunction find-most-common-edge ()
(bind ?all-edges (get-all-edges))
(bind ?unique-edges (remove-duplicates ?all-edges))
(bind ?largest-count 0)
(bind ?most-common (create$))
(foreach ?e ?unique-edges
(bind ?count (count-edge ?e ?all-edges))
(if (= ?count ?largest-count)
then
(bind ?most-common (create$ ?most-common ?e))
else
(if (> ?count ?largest-count)
then
(bind ?largest-count ?count)
(bind ?most-common (create$ ?e)))))
(return ?most-common))
CLIPS> (reset)
CLIPS> (find-most-common-edge)
(e f)
CLIPS>
Using rules:
CLIPS> (clear)
CLIPS>
(deftemplate chain
(slot id (default-dynamic (gensym*)))
(multislot edge (type SYMBOL)))
CLIPS>
(deftemplate count
(slot edge)
(multislot ids))
CLIPS>
(deffacts start
(chain (edge a b c d e f g))
(chain (edge d e f g h k l))
(chain (edge e o p q r s f))
(find-common-edge))
CLIPS>
(defrule create-count
(logical (find-common-edge))
(chain (id ?id) (edge $? ?e $?))
(not (count (edge ?e)))
=>
(assert (count (edge ?e) (ids ?id))))
CLIPS>
(defrule add-to-count
(logical (find-common-edge))
(chain (id ?id) (edge $? ?e $?))
?f <- (count (edge ?e) (ids $?ids))
(test (not (member$ ?id ?ids)))
=>
(modify ?f (ids ?ids ?id)))
CLIPS>
(defrule most-common-edge
(declare (salience -10))
?f <- (find-common-edge)
(count (edge ?e) (ids $?r1))
(not (and (count (edge ~?e) (ids $?r2))
(test (> (length$ ?r2) (length$ ?r1)))))
=>
(bind ?length (length$ ?r1))
(bind ?edges (create$))
(do-for-all-facts ((?c count))
(eq (length$ ?c:ids) ?length)
(bind ?edges (create$ ?edges ?c:edge)))
(assert (most-common-edges ?edges))
(retract ?f))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-1 (chain (id gen4) (edge a b c d e f g))
f-2 (chain (id gen5) (edge d e f g h k l))
f-3 (chain (id gen6) (edge e o p q r s f))
f-20 (most-common-edges e f)
For a total of 4 facts.
CLIPS>
I want to add a else part for below code as (assert (diabetes-assume false)). I glad if someone can help me to fix this issue.
(defrule diabetes-adult
(disease ?d)
(body-status ?b)
(age ?a&:(and (eq ?d none) (>= ?a 19) (< ?a 51) (or (eq ?b obesity) (eq ?b overweight) )))
=>
(assert (diabetes-assume true)))
You can assume as part of your initial state that diabetes is false and then define a higher salience rule (than the rules which rely on that assumption) to change the assumption to true:
(deffacts assumptions
(diabetes-assume false))
(defrule diabetes-adult-true
(declare (salience 10))
?f <- (diabetes-assume false)
(disease ?d)
(body-status ?b)
(age ?a&:(and (eq ?d none)
(>= ?a 19)
(< ?a 51)
(or (eq ?b obesity) (eq ?b overweight))))
=>
(retract ?f)
(assert (diabetes-assume true)))
Can someone explain me how can I import the WEKA created rules in CLIPS and evaluate its efficience in TRS and TES data?
The data I use
I have written 7 rules out of 20 from WEKA tree. I include also 3 instances from the glass datasheet
small test code
(deftemplate glass
(slot n(type FLOAT))
(slot m(type FLOAT))
(slot a(type FLOAT))
(slot b(type FLOAT))
(slot r(type FLOAT))
(slot s(type FLOAT))
(slot k(type FLOAT))
(slot c(type FLOAT)))
(deftemplate Type
(slot type))
(deffacts instances1
(glass (n 13.00)
(m 2.28)
(a 1.00)
(b 0.00)))
(deffacts instances2
(glass (n 13.70)
(m 1.80)
(a 1.40)
(b 0.00)))
(deffacts instances3
(glass (n 13.70)
(m 1.90)
(a 1.40)
(b 0.00)))
(defrule R1
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (<= ?m 2.41))
(glass (n ?n))
(test (<= ?n 13.78))
(glass (a ?a))
(test (<= ?a 1.38))
=>
(assert (Type (type buildwindnonfloat1)))
(printout t "buildwindnonfloat1 detected" crlf))
(defrule R2
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (<= ?m 2.41))
(glass (n ?n))
(test (<= ?n 13.78))
(glass (a ?a))
(test (> ?a 1.38))
(glass (m ?m))
(test (<= ?m 1.88))
=>
(assert (Type (type containers2)))
(printout t "containers2 detected" crlf))
(defrule R3
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (<= ?m 2.41))
(glass (n ?n))
(test (<= ?n 13.78))
(glass (a ?a))
(test (> ?a 1.38))
(glass (m ?m))
(test (> ?m 1.88))
=>
(assert (Type (type buildwindnonfloat3)))
(printout t "buildwindnonfloat3 detected" crlf))
(defrule R4
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (<= ?m 2.41))
(glass (n ?n))
(test (> ?n 13.78))
=>
(assert (Type (type tableware4)))
(printout t "tableware detected" crlf))
(defrule R5
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (> ?m 2.41))
(glass (a ?a))
(test (<= ?a 1.4))
(glass (m ?m))
(test (<= ?m 3.34))
(glass (a ?a))
(test (<= ?a 1.25))
=>
(assert (Type (type buildwindnonfloat5)))
(printout t "buildwindnonfloat5 detected" crlf))
(defrule R6
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (> ?m 2.41))
(glass (a ?a))
(test (<= ?a 1.4))
(glass (m ?m))
(test (<= ?m 3.34))
(glass (a ?a))
(test (> ?a 1.25))
=>
(assert (Type (type buildwindfloat6)))
(printout t "buildwindfloat6 detected" crlf))
(defrule R7
(glass (b ?b))
(test (<= ?b 0.27))
(glass (m ?m))
(test (> ?m 2.41))
(glass (a ?a))
(test (<= ?a 1.4))
(glass (m ?m))
(test (> ?m 3.34))
(glass (m ?m))
(test (<= ?m 3.82))
(glass (r ?r))
(test (<= ?r 1.51707))
(glass (r ?r))
(test (<= ?r 51596))
=>
(assert (Type (type buildwindfloat7)))
(printout t "buildwindfloat7 detected" crlf))
To convert your data, it's easiest to read the data from the file when your program is running and directly assert the facts. So if your data looks like the following with each entry on its own line
1.5159,13.24,3.34,1.47,73.1,0.39,8.22,0,0,'build wind non-float'
1.5167,13.24,3.57,1.38,72.7,0.56,8.44,0,0.1,'vehic wind float'
then your can read your data by reading each line as a single string, replacing the commas with spaces, and then splitting the string into multiple values. You can then have a separate rule map the values from your file to the appropriate slots in your deftemplate facts.
Store the expected result with each glass fact and then you can compare that value to the value that your rule is proposing.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate glass
(slot n (type FLOAT))
(slot m (type FLOAT))
(slot a (type FLOAT))
(slot b (type FLOAT))
(slot r (type FLOAT))
(slot s (type FLOAT))
(slot k (type FLOAT))
(slot c (type FLOAT))
(slot f (type FLOAT))
(slot type))
CLIPS>
(deftemplate input
(multislot data))
CLIPS>
(deffunction str-rpl (?str ?find ?replace)
(if (eq ?find "")
then
(return ?str))
(bind ?rs "")
(bind ?fl (str-length ?find))
(bind ?i (str-index ?find ?str))
(while (neq ?i FALSE)
(bind ?rs (str-cat ?rs (sub-string 1 (- ?i 1) ?str) ?replace))
(bind ?str (sub-string (+ ?i ?fl) (str-length ?str) ?str))
(bind ?i (str-index ?find ?str)))
(bind ?rs (str-cat ?rs ?str))
?rs)
CLIPS>
(defrule get-data
=>
(printout t "Input File? ")
(bind ?file (readline))
(if (not (open ?file data))
then
(printout t "Unable to open file" crlf)
(return))
(bind ?line (readline data))
(while (neq ?line EOF)
(bind ?line (str-rpl ?line "," " "))
(bind ?line (str-rpl ?line "'" "\""))
(assert (input (data (explode$ ?line))))
(bind ?line (readline data)))
(close data))
CLIPS>
(defrule convert-data
?i <- (input (data ?r ?n ?m ?a ?s ?k ?c ?b ?f ?type))
=>
(retract ?i)
(assert (glass (r ?r) (n ?n) (m ?m) (a ?a) (s ?s) (k ?k) (c ?c) (b ?b) (f ?f) (type ?type))))
CLIPS>
(defrule R1
(glass (b ?b)
(m ?m)
(n ?n)
(a ?a)
(type ?type))
(test (<= ?b 0.27))
(test (<= ?m 2.41))
(test (<= ?n 13.78))
(test (<= ?a 1.38))
=>
(printout t "buildwindnonfloat1 detected type = " ?type crlf))
CLIPS>
(defrule R2
(glass (b ?b)
(m ?m)
(n ?n)
(a ?a)
(type ?type))
(test (<= ?b 0.27))
(test (<= ?m 2.41))
(test (<= ?n 13.78))
(test (> ?a 1.38))
(test (<= ?m 1.88))
=>
(printout t "containers2 detected type = " ?type crlf))
CLIPS>
(defrule R3
(glass (b ?b)
(m ?m)
(n ?n)
(a ?a)
(type ?type))
(test (<= ?b 0.27))
(test (<= ?m 2.41))
(test (<= ?n 13.78))
(test (> ?a 1.38))
(test (> ?m 1.88))
=>
(printout t "buildwindnonfloat3 detected type = " ?type crlf))
CLIPS>
(defrule R4
(glass (b ?b)
(m ?m)
(n ?n)
(type ?type))
(test (<= ?b 0.27))
(test (<= ?m 2.41))
(test (> ?n 13.78))
=>
(printout t "tableware detected type = " ?type crlf))
CLIPS>
(defrule R5
(glass (b ?b)
(m ?m)
(a ?a)
(type ?type))
(test (<= ?b 0.27))
(test (> ?m 2.41))
(test (<= ?a 1.4))
(test (<= ?m 3.34))
(test (<= ?a 1.25))
=>
(printout t "buildwindnonfloat5 detected type = " ?type crlf))
CLIPS>
(defrule R6
(glass (b ?b)
(m ?m)
(a ?a)
(type ?type))
(test (<= ?b 0.27))
(test (> ?m 2.41))
(test (<= ?a 1.4))
(test (<= ?m 3.34))
(test (> ?a 1.25))
=>
(printout t "buildwindfloat6 detected type = " ?type crlf))
CLIPS>
(defrule R7
(glass (b ?b)
(m ?m)
(a ?a)
(r ?r)
(type ?type))
(test (<= ?b 0.27))
(test (> ?m 2.41))
(test (<= ?a 1.4))
(test (> ?m 3.34))
(test (<= ?m 3.82))
(test (<= ?r 1.51707))
(test (<= ?r 51596))
=>
(printout t "buildwindfloat7 detected type = " ?type crlf))
CLIPS> (reset)
CLIPS> (run)
Input File? weka.txt
buildwindfloat7 detected type = vehic wind float
CLIPS>
I am trying to solve a problem, where I have to fill a 5x5 matrix with letters A, B, C, D, and E. Each letter cannot occur more than once in each row and in each column. With some initial letter positions given.
I created every position as separate facts eg. "M 1 1 X".
I am struggling how to loop a defrule in way to assert a fact with correct letter and check the conditions again.
(defrule solveA5
?a <-(M 5 ?c X)
(not (M ?x ?c A))
=>
(retract ?a)
(assert (M 5 ?c A))
)
Code above for example is only to check presence of A in every position of 5th row, but the problem is that conditions are checked at the beginning only and instead of asserting correct fact and checking again it asserts A in every position.
I've tried using deffunction to loop defrule.
(deffunction solve (?letter)
(loop-for-count (?x 1 5) do
(loop-for-count (?y 1 5) do
(build (str-cat"defrule costam
?a <-(M ?x ?y X)
(not (and(M ?x ?a ?letter) (M ?b ?y ?letter))
=>
(retract ?a)
(assert (M ?x ?y ?letter))")
)
)
)
)
Unfortunately running
(solve A)
returns "FALSE" and doesn't modify any facts.
To handle iteration within rules, you must assert the iteration information as facts to allow the rules to match and modify this information. In the placement, it's not essential to do this in any particular order, so you can just assert information containing the rows, columns, and letters to place and allow the rules fire arbitrarily:
CLIPS>
(deftemplate element
(slot row)
(slot column)
(slot value))
CLIPS>
(deftemplate print
(slot row)
(slot column)
(slot end-of-row))
CLIPS>
(deffacts initial
(rows 1 2 3 4 5)
(columns 1 2 3 4 5)
(letters A B C D E))
CLIPS>
(defrule place
(rows $? ?r1 $?)
(columns $? ?c1 $?)
(letters $? ?l $?)
(not (element (row ?r1) (column ?c1)))
(not (and (element (row ?r2)
(column ?c2)
(value ?l))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))))
=>
(assert (element (row ?r1) (column ?c1) (value ?l))))
CLIPS>
(defrule print-start
(declare (salience -10))
(rows ?r $?)
(columns ?c $?rest)
=>
(assert (print (row ?r)
(column ?c)
(end-of-row (= (length$ ?rest) 0)))))
CLIPS>
(defrule print-next-column
(declare (salience -10))
?f <- (print (column ?c))
(columns $? ?c ?nc $?rest)
=>
(modify ?f (column ?nc)
(end-of-row (= (length$ ?rest) 0))))
CLIPS>
(defrule print-next-row
(declare (salience -10))
?f <- (print (column ?c) (row ?r))
(columns $?first ?c)
(rows $? ?r ?nr $?)
=>
(if (= (length$ ?first) 0)
then
(bind ?eor TRUE)
(bind ?nc ?c)
else
(bind ?eor FALSE)
(bind ?nc (nth$ 1 ?first)))
(modify ?f (row ?nr)
(column ?nc)
(end-of-row ?eor)))
CLIPS>
(defrule print-placed
(print (row ?r) (column ?c) (end-of-row ?eor))
(element (row ?r) (column ?c) (value ?l))
=>
(if ?eor
then
(printout t ?l crlf)
else
(printout t ?l " ")))
CLIPS>
(defrule print-unplaced
(print (row ?r) (column ?c) (end-of-row ?eor))
(not (element (row ?r) (column ?c)))
=>
(if ?eor
then
(printout t "?" crlf)
else
(printout t "? ")))
CLIPS> (reset)
CLIPS> (run)
E D C B A
? C D A B
? B A D C
? A B C D
A ? ? ? E
CLIPS>
In this example, the print rules iterate over the rows and columns by storing the iteration information in facts. You can see how much more complicated this is than the place rule which assigns the elements in an arbitrary manner.
Whether you assign the values arbitrarily or in a specific order, it's possible to assign values that prevent a solution, so you must implement backtracking in order to guarantee finding the solution if one exists. In this example, the facts store information about the order of the value placements and the values that have been tried:
CLIPS> (clear)
CLIPS>
(deftemplate element
(slot row)
(slot column)
(slot value (default unset))
(multislot values)
(slot placement))
CLIPS>
(deffacts initial
(placement 0)
(rows 1 2 3 4 5)
(columns 1 2 3 4 5)
(letters A B C D E))
CLIPS>
(defrule prime
(placement ?p)
(rows $? ?r $?)
(columns $? ?c $?)
(letters $?l)
(not (element (placement ?p)))
(not (element (row ?r) (column ?c)))
=>
(assert (element (placement ?p) (values ?l) (row ?r) (column ?c))))
CLIPS>
(defrule place-good
?f1 <- (placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(row ?r1)
(column ?c1)
(values ?v $?rest))
(not (and (element (row ?r2)
(column ?c2)
(value ?v))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))))
=>
(retract ?f1)
(assert (placement (+ ?p 1)))
(modify ?f2 (value ?v) (values ?rest)))
CLIPS>
(defrule place-bad
(placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(row ?r1)
(column ?c1)
(values ?v $?rest))
(element (row ?r2)
(column ?c2)
(value ?v))
(test (or (= ?r1 ?r2) (= ?c1 ?c2)))
=>
(modify ?f2 (values ?rest)))
CLIPS>
(defrule backtrack
?f1 <- (placement ?p)
?f2 <- (element (placement ?p)
(value unset)
(values))
?f3 <- (element (placement =(- ?p 1))
(value ~unset))
=>
(retract ?f1)
(assert (placement (- ?p 1)))
(retract ?f2)
(modify ?f3 (value unset)))
CLIPS>
(defrule print
(declare (salience -10))
(rows $?rows)
(columns $?columns)
=>
(progn$ (?r ?rows)
(progn$ (?c ?columns)
(if (not (do-for-fact ((?f element))
(and (= ?r ?f:row) (= ?c ?f:column))
(printout t ?f:value " ")))
then
(printout t "? ")))
(printout t crlf)))
CLIPS> (reset)
CLIPS> (run)
B C D E A
A B C D E
C A E B D
D E A C B
E D B A C
CLIPS>
The print rules have been simplified into a single rule that iterates over the row and columns in the actions of the rule and uses the fact query functions to retrieve values that have been assigned.
The program also works if you preassign some of the values:
CLIPS> (reset)
CLIPS> (assert (element (row 1) (column 1) (value A)))
<Fact-5>
CLIPS> (assert (element (row 3) (column 3) (value C)))
<Fact-6>
CLIPS> (assert (element (row 5) (column 4) (value E)))
<Fact-7>
CLIPS> (run)
A C E D B
B A D C E
D E C B A
E D B A C
C B A E D
CLIPS>
I'm asking if there is a possibility of accessing a get the index of fact in RHS of defrule ?
It gives me that undefined every time I try to index a fact in a RHS of defrule.
because I have a while loop , I want to be able to modify elevator fact depending on my input data.
(deftemplate elevator
(slot goal))
(deffacts elevator
(elevator (goal 0)))
(defrule read-data
=>
?f1 <- (elevator)
(modify ?f2 (goal 1))
)
this an example of my code , since I can't put all online :
(deftemplate data
(slot data)
)
(deffacts data
(data (data 1))
)
(defrule rule1
?f1 <-(data)
=>
(bind ?value (readline input) )
(while (neq ?value EOF)
do
(bind ?data (fact-slot-value ?f1 data))
(printout t "data " ?data crlf )
(retract ?f1)
(modify ?f1 (data ?value))
(bind ?value (readline input)
)
)
)
this is my input file :
2
3
4
5
6
7
this is what I'm getting :
CLIPS> (run)
data 1
data FALSE
data FALSE
data FALSE
data FALSE
data FALSE
CLIPS>
I want it to print out
data 2
data 3
data 4 ..ect
You can do it this way from the RHS of a rule, but if your rule actually has no LHS conditions, it's pointless to use a rule to change the value of the fact. Just use a function.
CLIPS>
(deftemplate elevator
(slot goal))
CLIPS>
(deffacts elevator
(elevator (goal 0)))
CLIPS>
(defrule read-data
=>
(do-for-fact ((?f elevator)) TRUE
(modify ?f (goal 1))))
CLIPS> (watch facts)
CLIPS> (reset)
<== f-0 (initial-fact)
==> f-0 (initial-fact)
==> f-1 (elevator (goal 0))
CLIPS> (run)
<== f-1 (elevator (goal 0))
==> f-2 (elevator (goal 1))
CLIPS>
Alternately, you can bind the fact you want to modify in the conditions of the rule:
CLIPS> (clear)
CLIPS>
(deftemplate elevator
(slot goal))
CLIPS>
(deffacts elevator
(elevator (goal 0)))
CLIPS>
(defrule read-data
?f <- (elevator (goal 0))
=>
(modify ?f (goal 1)))
CLIPS> (watch facts)
CLIPS> (reset)
<== f-0 (initial-fact)
==> f-0 (initial-fact)
==> f-1 (elevator (goal 0))
CLIPS> (run)
<== f-1 (elevator (goal 0))
==> f-2 (elevator (goal 1))
CLIPS>
Updated:
You can get your original rule to "work" by removing the retract and rebinding ?f1 to the value returned by modify:
CLIPS> (clear)
CLIPS>
(deftemplate data
(slot data))
CLIPS>
(deffacts data
(data (data 1)))
CLIPS>
(defrule rule1
?f1 <- (data)
=>
(bind ?value (readline input))
(while (neq ?value EOF)
(bind ?data (fact-slot-value ?f1 data))
(printout t "data " ?data crlf )
(bind ?f1 (modify ?f1 (data ?value)))
(bind ?value (readline input))))
CLIPS> (reset)
CLIPS> (open input.txt input)
TRUE
CLIPS> (run)
data 1
data 2
data 3
data 4
data 5
data 6
CLIPS> (close input)
TRUE
CLIPS>
It's still suspiciously complicated to be modifying the same fact multiple times on the RHS.