What's the return value of CLIPS' do-for-fact if fact has been found? - clips

The CLIPS reference manual explains about do-for-fact:
If a fact-set satisfies
the query, the specified action is executed, and the function is immediately terminated. The
return value is the evaluation of the action. If no fact-set satisfied the query, then the return value
is the symbol FALSE.
However, I cannot find any details on what the "evaluation of the action" means in general.
Is it safe to assume that do-for-fact always returns a value not equal to FALSE if a fact has been found?
Is the following code snippet correct?
(if (not (do-for-fact ((?p1 girl boy woman man)
(?p2 girl boy woman man)
(?p3 girl boy woman man))
(and (= ?p1:age ?p2:age ?p3:age)
(neq ?p1 ?p2)
(neq ?p1 ?p3)
(neq ?p2 ?p3))
(printout t ?p1:name " " ?p2:name " " ?p3:name crlf)))
then
(printout t "Nobody found" crlf)
)

Action refers to the BNF description of the function syntax:
(do-for-fact <fact-set-template> <query> <action>*)
This action term is the same term used in the body of a deffunction:
(deffunction <name> [<comment>]
(<regular-parameter>* [<wildcard-parameter>]) <action>*)
The return value in both cases is the last action evaluated. If the last action evaluated returns the value FALSE, then the do-for-fact function will return the value FALSE just as it would if there was no fact-set that satisfied the query.
In your example, the printout function has no return value which is treated as a non-FALSE value by the not function, so it will work as you expect
CLIPS> (printout t)
CLIPS> (not (printout t))
FALSE
CLIPS>
If you had included the symbol FALSE after the printout call, then the return value of the do-for-fact call would always be FALSE regardless of whether any fact-set satisfied the query.
(printout t ?p1:name " " ?p2:name " " ?p3:name crlf)
FALSE))

Related

How do I add a global variable to count the number of yes or no responses?

I am working on a nutrition diagnosis system where users are asked questions/symptoms and they respond by entering yes or no. I want to track the count of yes or no and make calculations with them. Like store the count of yes or no in global variables. I already have a function for the calculation but unsure how to capture the yes or no from the user input. I am new to using Jess rules. Below I have added codes of the working rule.
(defrule menu::initialize
(diagnosis)
=>
(assert
(question (ident q21) (text "Does the child's hair tend to be slight? (Yes or No)") (type yes-no))
(question (ident q22) (text "Does the child's hair tend to be reddish? (Yes or No)") (type yes-no))
(question (ident q23) (text "Is the child often affected by ISPA/ TBC? (Yes or No)") (type yes-no))
(question (ident q24) (text "Does the child's hair tend to be easily falls off? (Yes or No)") (type yes-no))
(question (ident q25) (text "Is there any abnormality on the child's complexion? (Yes or No)") (type yes-no))
(question (ident q26) (text "Is there any swelling on the child's face? (Yes or No)") (type yes-no))
)
(menu::init)
)
You have shown a rule called "menu::initialize" which inserts some facts called "question". You need a rule to fire on these facts, and this rule would then contain a statement to add 1 to a global variable. You can find examples for rules and for using global variables in the Jess manual.
Please don't expect someone on SO to do your homework for you.
I implemented the suggested solution above and got exactly what I was looking for.
My implementation below:.. Might not be an optimal solution but it works. Thanks SO :D
(defrule get-y21
"Add 1 to global variable for every yes answer from question21"
(answer (ident q21) (text yes ))
=>
(bind ?*countyes* (+ ?*countyes* 1))
)
(defrule get-n21
"Add 1 to global variable for every no answer from question21 "
(answer (ident q21) (text no ))
=>
(bind ?*countno* (+ ?*countno* 1))
)

Testing for presence in a multifield - CLIPS

I want to add a condition to the LHS of a rule which tests if a certain symbol appears somewhere in the multislot of a template.
For example, in the code below I would like to substitute the comment with whatever expression makes this work.
(deftemplate foo
(slot field
(type STRING)
)
(multislot multifield
(type INTEGER)
)
)
(deftemplate bar
(slot field
(type INT)
)
)
(defrule rule
(foo (field ?f1) (multifield $?mf1))
(bar (field ?f2))
; IF f2 IS AN ELEMENT OF mf1
=>
(assert (relation f1 f2))
)
What is the syntax here?
I needed to use the member$ function!
(test (member$ ?f2 ?mf1))

CLIPS (Expert System) write rules that add and remove values from the queue

I need help to write two rules, that add and remove values from queue. Rule that removes value from queue must use forall structure.
As far as I know, CLIPS does not have arrays, stack, lists or any other type of collections. So I have started with defining template queue with a slot item, that should represent value of a queue, but have not succeeded with the rules. Does anyone have any idea how this can be done?
CLIPS has multifield objects which act as lists.
You can define your queue as a global variable and modify it in your rules as for this example (LIFO queue).
CLIPS> (defglobal ?*queue* = (create$))
; add "foo" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "foo"))
("foo")
; add "bar" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "bar"))
("bar" "foo")
; remove first element from the queue
(bind ?*queue* (delete$ ?*queue* 1 1))
("foo")

How do I retrieve fact index in clips in a deffunction?

(deffunction up ()
?fact <- u
(retract ?fact)
(assert (u green))
)
I'm trying to get something like this to work, a function to alter the states of facts, but with this it gives me an error of like ?fact is not defined. But I have done this in a defrule. Why is this not working?
Functions receive input through their parameters. Rules receive input through their patterns. If you want to pattern match, use a rule:
(defrule up
?fact <- (u)
=>
(retract ?fact)
(assert (u green)))
Alternately if you need to iterate over the existing set of facts for a deftemplate, you can use the fact set query functions (do-for-fact, do-for-all-facts, ...):
(deffunction up ()
(do-for-fact ((?fact u)) TRUE
(retract ?fact))
(assert (u green)))

CLIPS finding facts not working

I have the following deftemplates in CLIPS (6.3):
(deftemplate A ( slot a ) (slot b) )
(deftemplate forSearch (slot property)(slot value))
I need to read the pair (property, value) from input, and then find the fact A whose value in the slot property is value.
If I do something like this:
(defrule r2
(forSearch (property ?c)(value ?d))
(A (?c ?d))
=>
(printout t "debug" crlf)
)
I get the following error:
[PRNTUTIL2] Syntax Error: Check appropriate syntax for deftemplate patterns.
ERROR:
(defrule MAIN::r2
(forSearch (property ?c) (value ?d))
(A (?c
What should I do now?
You have to write to slot name in the pattern matching part of the rule.
The correct sintax is:
(defrule r2
(forSearch (property ?c)(value ?d))
(A (a ?c) (b ?d))
=>
(printout t "debug" crlf)
)
I don't understand what you want to accomplish, and I know it's late, but hope it helps.

Resources