How to accumulate slots of facts? - clips

I have the following two deftemplates:
(deftemplate effect (slot type) (slot value) (slot explanation))
(deftemplate result (slot type) (slot total_value) (multislot total_explanation))
and the following deffacts:
(effect (type A) (value 1) (explanation "A is 1"))
(effect (type A) (value 2) (explanation "A is 2"))
(effect (type B) (value 3) (explanation "B is 3"))
(effect (type B) (value 4) (explanation "B is 4"))
I want to sum up the total values for facts of the same type resulting in:
(result (type A) (total_value 3) (total_explanation "A is 1" "A is 2"))
(result (type B) (total_value 7) (total_explanation "B is 3" "B is 4"))
How would I accumulate the slots of facts? Here's what I tried:
(defrule accumulate_typeA
(exists (effect (type A)))
=>
(bind ?sum 0)
(do-for-all-facts ((?f effect) (bind ?sum (+ ?sum ?f:value))
(bind ?expl (create$))
(do-for-all-facts ((?f effect) (bind ?expl (inserts ?f:explanation))))
(assert (result (type A) (total_value ?sum) (total_explanation ?expl))

CLIPS (6.4 2/9/21)
CLIPS>
(deftemplate effect
(slot type)
(slot value)
(slot explanation))
CLIPS>
(deftemplate result
(slot type)
(slot total_value)
(multislot total_explanation))
CLIPS>
(deffacts initial
(effect (type A) (value 1) (explanation "A is 1"))
(effect (type A) (value 2) (explanation "A is 2"))
(effect (type B) (value 3) (explanation "B is 3"))
(effect (type B) (value 4) (explanation "B is 4")))
CLIPS>
(defrule accumulate_all_types
=>
(bind ?types (create$))
(do-for-all-facts ((?f effect)) TRUE
(if (not (member$ ?f:type ?types))
then
(bind ?types ?types ?f:type)))
(foreach ?t ?types
(bind ?sum 0)
(bind ?expl (create$))
(do-for-all-facts ((?f effect)) (eq ?f:type ?t)
(bind ?sum (+ ?sum ?f:value))
(bind ?expl ?expl ?f:explanation))
(assert (result (type ?t)
(total_value ?sum)
(total_explanation ?expl)))))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-1 (effect (type A) (value 1) (explanation "A is 1"))
f-2 (effect (type A) (value 2) (explanation "A is 2"))
f-3 (effect (type B) (value 3) (explanation "B is 3"))
f-4 (effect (type B) (value 4) (explanation "B is 4"))
f-5 (result (type A) (total_value 3) (total_explanation "A is 1" "A is 2"))
f-6 (result (type B) (total_value 7) (total_explanation "B is 3" "B is 4"))
For a total of 6 facts.
CLIPS>

Related

Clips range find between 2 json inputs

I want to implemen a rule ;
Lets assume that ı have one input.json it consist a name value pair.Example;
{
"quality":"300"
}
I have another constant json ,Example
[{
"up":"100",
"down":"0",
"data":"xx"
},
{
"up":"200",
"down":"100",
"data":"yy"
},
,
{
"up":"300",
"down":"200",
"data":"zz"
}
]
I am trying to find propert value for data for which up and down range.
for this one ı, have to get zz because "quality":"300" is between 200-300.
how can ı success this one in clips rule.
CLIPS (6.31 6/12/19)
CLIPS>
(deftemplate pair
(slot name)
(slot value))
CLIPS>
(deffacts pairs
(pair (name "quality") (value 300)))
CLIPS>
(deftemplate data
(slot name)
(slot up)
(slot down))
CLIPS>
(deffacts data-values
(data (name "xx") (up 100) (down 0))
(data (name "yy") (up 200) (down 100))
(data (name "zz") (up 300) (down 200)))
CLIPS>
(defrule in-range
(pair (name "quality")
(value ?value))
(data (name ?name)
(up ?up)
(down ?down))
(test (and (> ?value ?down) (<= ?value ?up)))
=>
(printout t ?name " is in range." crlf))
CLIPS> (reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (pair (name "quality") (value 300))
f-2 (data (name "xx") (up 100) (down 0))
f-3 (data (name "yy") (up 200) (down 100))
f-4 (data (name "zz") (up 300) (down 200))
For a total of 5 facts.
CLIPS> (agenda)
0 in-range: f-1,f-4
For a total of 1 activation.
CLIPS> (run)
zz is in range.
CLIPS>

Expected argument #1 to be of type integer or float on CLIPS code

I have a problem with my code that is to recommend a herbicide and an application rate for it as appropriate in a given field situation.
(deftemplate plant
(multislot weed)
(multislot crop))
(deftemplate Herbicide
(slot orgmatter)
(slot sencor)
(slot lasso)
(slot bicep))
(deffacts p
(plant (weed B) (crop C S))
(plant (weed B G) (crop C S))
(plant (weed B G) (crop C)))
(deffacts H
(Herbicide (orgmatter 1) (sencor 0.0) (lasso 2.0) (bicep 1.5))
(Herbicide (orgmatter 2) (sencor 0.75) (lasso 1.0) (bicep 2.5))
(Herbicide (orgmatter 3) (sencor 0.75) (lasso 0.5) (bicep 3.0)))
(defrule read-input
=>
(printout t "what is type of crop? (C:Corn , S:Soyabeans): ")
(assert (crop(read)))
(printout t "what is type of weed? (B:broadleaf , G:gress): ")
(assert (weed(read)))
(printout t "what is the organic matter? (1:<2% ,2: 2-4%, 3: >4%: ")
(assert (orgmatter(read))))
(defrule check-input
(crop ?crop)
(weed ?weed)
(orgmatter ? orgmatter)
(plant (weed $?weed1) (crop $?crop1))
(Herbicide (orgmatter ?orgmatter1) (sencor ?sencor1) (lasso ?lasso1)(bicep ?bicep1))
(test (member$ ?crop ?crop1))
(test (member$ ?weed ?weed1))
(test (= orgmatter ?orgmatter1))
=>
(printout t "you can use" ?sencor1 " pt/ac of sencor" crlf)
(printout t "you can use" ?lasso1 " pt/ac of lasso" crlf)
(printout t "you can use" ?bicep1 " pt/ac of bicep" crlf)))
The error is the following: Function = expected argument#1 to be of type integer or float
Your code has an extra ) at the end.
In defrule check-input, you have a test:
(test (= orgmatter ?orgmatter1))
Which is comparing a SYMBOL orgmatter with the variable ?orgmatter1. The = test works only with numerals. If you want to compare SYMBOLs or STRINGs, you need to use the eq function.
(test (eq orgmatter ?orgmatter1))
Nevertheless if you are not using ?orgmatter1 anywhere else, it is more effective to do a literal match rather than a test.
(Herbicide (orgmatter orgmatter)
(sencor ?sencor1)
(lasso ?lasso1)
(bicep ?bicep1))

how to get the index of facts in RHS of rule?

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.

CLIPS counting facts or template instances that match the pattern

First I declare:
(deftemplate worker
(slot id
(type STRING)
(default ?DERIVE))
(slot salary
(type FLOAT)
(default ?DERIVE)))
then I add:
(assert(worker(id "a")(salary 30.0)))
(assert(worker(id "b")(salary 40.0)))
(assert(worker(id "c")(salary 60.0)))
(assert(worker(id "d")(salary 70.0)))
(assert(worker(id "e")(salary 10.0)))
How can I count how many 'workers' I have?
How can I count for example how many workers have salary over 30?
Use the fact-set query functions:
CLIPS>
(deftemplate worker
(slot id (type STRING) (default ?DERIVE))
(slot salary (type FLOAT) (default ?DERIVE)))
CLIPS> (assert (worker (id "a") (salary 30.0)))
<Fact-1>
CLIPS> (assert (worker (id "b") (salary 40.0)))
<Fact-2>
CLIPS> (assert (worker (id "c") (salary 60.0)))
<Fact-3>
CLIPS> (assert (worker (id "d") (salary 70.0)))
<Fact-4>
CLIPS> (assert (worker (id "e") (salary 10.0)))
<Fact-5>
CLIPS> (find-all-facts ((?f worker)) (> ?f:salary 30.0))
(<Fact-2> <Fact-3> <Fact-4>)
CLIPS> (length$ (find-all-facts ((?f worker)) (> ?f:salary 30.0)))
3
CLIPS> (do-for-all-facts ((?f worker)) (> ?f:salary 30.0) (printout t ?f:id crlf))
b
c
d
CLIPS>

clips defrule doesn't work

i have deftemplate for url that contains url itself and integer counter :
(deftemplate url_t
(slot counter
(type INTEGER)
(default 0))
(slot url
(type STRING)
(default "")))
and i am trying to define the rule to print url string if counter value >0
(defrule print-url
(url_t (counter ?counter) (url ?url))
(test (> ?counter 0))
=>
(printout t "url is " ?url crlf)
)
But when i try to change the values of url_t:
(assert url_t (counter 2) (url "hello hello"))
The rule is not executed. Where's my error?
If the assert statement in your description is exactly what you entered, then that's your problem because the syntax is invalid. Other than that, there's nothing wrong with the syntax of your deftemplate or defrule:
CLIPS> (clear)
CLIPS> (unwatch all)
CLIPS>
(deftemplate url_t
(slot counter
(type INTEGER)
(default 0))
(slot url
(type STRING)
(default "")))
CLIPS>
(defrule print-url
(url_t (counter ?counter) (url ?url))
(test (> ?counter 0))
=>
(printout t "url is " ?url crlf))
CLIPS> (assert (url_t (counter 2) (url "hello hello")))
<Fact-1>
CLIPS> (facts)
f-0 (initial-fact)
f-1 (url_t (counter 2) (url "hello hello"))
For a total of 2 facts.
CLIPS> (agenda)
0 print-url: f-1
For a total of 1 activation.
CLIPS> (run)
url is hello hello
CLIPS> (modify 1 (counter 3) (url "goodbye goodbye"))
<Fact-2>
CLIPS> (agenda)
0 print-url: f-2
For a total of 1 activation.
CLIPS> (run 1)
url is goodbye goodbye
CLIPS> (modify 2 (counter 0) (url "won't fire"))
<Fact-3>
CLIPS> (agenda)
CLIPS>

Resources