how to fuzzify in fuzzyclips? - clips

i want to write a project get a precise value for calorie to calculate the precise value of the then part(how much weight increased?).this is my rule:
if calorie is high then increase weight
for this i have this set for calorie:
(highCalorie (20 0)(40 .2) (60 .5) (100 .8) (180 1))
and in the other hand for value of increase weight i have this set:
(increase(50 0) (100 .4) (120 .8) (150 1))
in other word i want to map a value for calorie to increase weight.
for do this i write this code :
(deftemplate calories
20 180
(high(20 0)(40 .2) (60 .5) (100 .8) (180 1))
)
(deftemplate fat
50 150
(increase(50 0) (100 .4) (120 .8) (150 1))
)
; We first get a precise value for calorie and fuzzify it.
(defrule getCalorie
(declare (salience 100))
=>
(printout t "Enter calorie: ")
(bind ?t (read))
(assert (calorie ?t))
)
(defrule fuzzifyCalorie
(calorie ?t)
=>
(assert (calories (?t 0) (?t .2) (?t .5)(?t .8)(?t 1))))
; Here we add rules to prescribe amounts of increased weight
(defrule result
(declare (salience -1))
(calories high)
=>
(assert (fat increase)))
(defrule ShowPenicillin
(declare (salience -100))
?f <- (fat ?p)
=>
(printout t "for this colrie" (moment-defuzzify ?f) " grams of fat increased to weight" crlf))
what is my mistake?
thanks alot.

Your deftemplates have missing parentheses. The corrected code is
(deftemplate calories
20 180
((high (20 0)
(40 .2)
(60 .5)
(100 .8)
(180 1))))
(deftemplate fat
50 150
((increase (50 0)
(100 .4)
(120 .8)
(150 1))))

Related

Round off floating point number to two decimal places in CLIPS

CLIPS gives a floating point number upto many decimal places.
e.g
CLIPS> ( / 4 3)
1.33333333333333
How do I get a value rounded off to two decimal places (1.33 in this case)
CLIPS (6.31 6/12/19)
CLIPS> (bind ?n (/ 4 3))
1.33333333333333
CLIPS> (/ (integer (* ?n 100)) 100)
1.33
CLIPS>
(deffunction precision (?num ?digits)
(bind ?m (integer (** 10 ?digits)))
(/ (integer (* ?num ?m)) ?m))
CLIPS> (precision ?n 2)
1.33
CLIPS> (precision ?n 4)
1.3333
CLIPS> (precision ?n 0)
1.0
CLIPS>

defrule never makes it in the agenda | CLIPS

I want to build an expert system in which in a case of emergency at a building with some floors (it needs to work for any amount of floors) the elevator should take the people into the ground.
The thing is, that the defrule to send the elevator at any floor never makes it in the agenda, so the system just does nothing. The correct action should be to fire the rule and then another rule that takes the people from the floor.
The code for the defrule is this:
(defrule move_to_floor "elevator moves to any floor "
?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
(floor ?fl&~?x has ?n adult and ?m minor people)
(test (> (+ ?n ?m) 0))
=>
(retract ?i)
(assert (elevator is_at floor ?fl has ?y adults and ?z minors))
)
The facts as they have been initialized from the user in another defrule above are these:
f-0 (initial-fact)
f-1 (elevator is_at 0 has 0 adults and 0 minors)
f-3 (capacity 4)
f-4 (floors 3)
f-5 (initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
f-6 (floor 3 has 2 adult and 1 minor people)
f-7 (floor 2 has 4 adult and 5 minor people)
f-8 (floor 1 has 1 adult and 2 minor people)
I can't seem to find the solution. Also, I'm using deffacts and not deftemplate as I have seen many people using on the internet.
You can use the matches command to see which patterns in a rule are matched.
CLIPS (6.31 2/3/18)
CLIPS>
(defrule move_to_floor "elevator moves to any floor "
?i <- (elevator is_at floor ?x has ?y adults and ?z minors)
(floor ?fl&~?x has ?n adult and ?m minor people)
(test (> (+ ?n ?m) 0))
=>
(retract ?i)
(assert (elevator is_at floor ?fl has ?y adults and ?z minors)))
CLIPS>
(deffacts initial
(elevator is_at 0 has 0 adults and 0 minors)
(capacity 4)
(floors 3)
(initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
(floor 3 has 2 adult and 1 minor people)
(floor 2 has 4 adult and 5 minor people)
(floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (matches move_to_floor)
Matches for Pattern 1
None
Matches for Pattern 2
f-5
f-6
f-7
Partial matches for CEs 1 - 2
None
Activations
None
(3 0 0)
CLIPS>
In this case, the first pattern is not matched. That's because your pattern expects is_at floor ?x but your fact contains is_at 0 (the symbol floor is missing in your fact). If you correct this issue, the rule will be placed on the agenda.
CLIPS>
(deffacts initial
(elevator is_at floor 0 has 0 adults and 0 minors)
(capacity 4)
(floors 3)
(initCanEnter 0) ;At 0 this prevents from entering the init_defrule again
(floor 3 has 2 adult and 1 minor people)
(floor 2 has 4 adult and 5 minor people)
(floor 1 has 1 adult and 2 minor people))
CLIPS> (reset)
CLIPS> (agenda)
0 move_to_floor: f-1,f-7
0 move_to_floor: f-1,f-6
0 move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>
If you issue a (run) command at this point, the rules will endlessly fire in a loop moving from floor to floor, so that's something you'll need to address next.
If you use deftemplate facts rather than ordered facts, you'll get an error if you misspell slot names, so it's better to use these if you have a fact with multiple attributes.
CLIPS> (clear)
CLIPS>
(deftemplate elevator
(slot at_floor (type INTEGER))
(slot adults (type INTEGER))
(slot minors (type INTEGER)))
CLIPS>
(deftemplate floor
(slot # (type INTEGER))
(slot adults (type INTEGER))
(slot minors (type INTEGER)))
CLIPS>
(deffacts initial
(elevator (at_floor 0))
(capacity 4)
(floors 3)
(initCanEnter 0)
(floor (# 3) (adults 2) (minors 1))
(floor (# 2) (adults 4) (minors 5))
(floor (# 1) (adults 1) (minors 2)))
CLIPS>
(defrule move_to_floor
?i <- (elevator (at_floor ?x))
(floor (# ?fl&~?x) (adults ?n) (minors ?m))
(test (> (+ ?n ?m) 0))
=>
(modify ?i (at_floor ?fl)))
CLIPS> (reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (elevator (at_floor 0) (adults 0) (minors 0))
f-2 (capacity 4)
f-3 (floors 3)
f-4 (initCanEnter 0)
f-5 (floor (# 3) (adults 2) (minors 1))
f-6 (floor (# 2) (adults 4) (minors 5))
f-7 (floor (# 1) (adults 1) (minors 2))
For a total of 8 facts.
CLIPS> (agenda)
0 move_to_floor: f-1,f-7
0 move_to_floor: f-1,f-6
0 move_to_floor: f-1,f-5
For a total of 3 activations.
CLIPS>

How to fuzify a crispy variable

I read some examples about how to fuzify a variable in FuzzyClips. I tried it by myself but i got some strange behaviour:
(deftemplate age-template
0 100 years ; Universe
(
(young (15 0.75) (17 1) (19 1))
(mature (18 0.75) (25 1) (30 0.25))
(adult (30 0.5) (40 1) (50 0.75))
(old (40 0.25) (50 0.75) (65 1) )
)
)
(deftemplate person
(slot name (type STRING))
(slot age (type INTEGER))
(slot city (type STRING))
)
(deffacts start
(person (name "John") (age 25) (city "London"))
(person (name "Mike") (age 55) (city "London"))
(person (name "Eva") (age 35) (city "London"))
)
(defrule fuzzify
(person (name ?name) (age ?age))
=>
(assert(age-template (?age 0.0) (?age 1.0) (?age 0.0)))
)
I don't know exactly what those "???" really mean and why each fact is being retracted after being asserted. I also have another doubt, i tried to print not only the age, but also the name and the age of each person with:
(defrule fuzzify
(person (name ?name)(age ?age))
=>
(assert (person-is ?name age-template (?age 0.0) (?age 1.0) (?age 0.0)))
)
But i got error "a function name must be a symbol".
So i solved it. I read that getting ??? is a common behaviour. So the solution is:
Create another deftemplate that will be the structure of the person name with their fuzzy age. In the rule's consecuent, instanciate the deftemplate asserting someone's name with the fuzzy age.
(deftemplate age-template
0 100 years ; Universe
(
(young (15 0.75) (17 1) (19 1))
(mature (18 0.75) (25 1) (30 0.25))
(adult (30 0.5) (40 1) (50 0.75))
(old (40 0.25) (50 0.75) (65 1) )
)
)
(deftemplate person
(slot name (type STRING))
(slot age (type INTEGER))
(slot city (type STRING))
)
(deftemplate fuzzyfication
(slot nameperson (type STRING))
(slot agefuzzy (type FUZZY-VALUE age-template))
)
(deffacts start
(person (name "John") (age 25) (city "London"))
(person (name "Mike") (age 55) (city "London"))
(person (name "Eva") (age 35) (city "London"))
)
(defrule fuzzify
(person (name ?name) (age ?age))
=>
(assert(fuzzyfication (nameperson ?name)(agefuzzy (?age 0.0) (?age 1.0) (?age 0.0))))
)
And the execution returns:

CLIPS: difference between two lists of facts

If I have a bunch of facts like (example (fact 1)), (example (fact 2)), (example (fact 3)), and have another list of facts like (myfact (number 2)), how can I perform a printout on each item in the first list that is not in the second (based on the number in the fact/number slots)? I suspect I need do-for-all-facts, but I'm not sure exactly how. Here's my incomplete code:
(deffunction difference ()
(do-for-all-facts ((?f1 example)) TRUE
(find-all-facts ((?f2 myfact)) (eq 1 1))
(if (somehow check if ?f1:fact does not equal ANY of number slots in ?f2) then
(printout t "..." crlf))))
CLIPS> (clear)
CLIPS> (deftemplate example (slot fact))
CLIPS> (deftemplate myfact (slot number))
CLIPS>
(deffacts start
(example (fact 1))
(example (fact 2))
(example (fact 3))
(myfact (number 2))
(myfact (number 4)))
CLIPS>
(deffunction difference ()
(do-for-all-facts ((?f1 example))
(not (any-factp ((?f2 myfact)) (eq ?f1:fact ?f2:number)))
(printout t "difference " ?f1:fact crlf)))
CLIPS> (reset)
CLIPS> (difference)
difference 1
difference 3
CLIPS>
(defrule difference
(example (fact ?n))
(not (myfact (number ?n)))
=>
(printout t "difference " ?n crlf))
CLIPS> (run)
difference 3
difference 1
CLIPS>

How can I run the clips with out reset the fact when using CLIPS

Here is my situation:
I want to run the CLIPS periodically and the system can record how many times it runs.
for example: I type in the terminal "run" many times to call the system periodically. then the system can record how many the system runs and show it on the screen. Here is my .clp file
(defglobal ?*lock* = 0)
(deftemplate counter
(slot number))
(deffacts initial_data
(counter (number 0))
)
(defrule set_counter
?f<-(counter (number ?x))
(test (= ?*lock* 0))
=>
(bind ?*lock* 1)
(printout t "plus 1" crlf)
(modify ?f (number (+ ?x 1)))
)
(defrule show_result
?f<-(counter (number ?x))
(test (= ?*lock* 1))
=>
(printout t "the counter value has been changed:" crlf)
(ppfact (fact-index ?f) t)
(bind ?*lock* 0)
)
I use a global value as a lock to control the rules and store the running times in the fact named counter. Now is my problem: Once the system finishes running for the first time. There are no rules in the agenda any more. I want the system can run again with out resetting the facts and the system can process the facts saved form the first running process. How can I refresh the agenda or rematch the rule without reset the facts?
I have find some commands like (refresh rule-name) and (refresh-agenda) but they can not solve my problem. I just type in "(refresh set_counter)" and "(refresh-agenda)" after "(run)". However, no rules are added into agenda.
I don't know if there are solution to my problem or clips can not work like this?
Another question is I try (refresh rule-name) with
(defglobal ?*lock* = 0)
(deftemplate counter
(slot number))
(deftemplate set
(slot number))
(deffacts initial_data
(counter (number 0))
)
(defrule set_counter
(initial-fact)
=>
(bind ?*lock* (+ ?*lock* 1))
(printout t ?*lock* crlf)
)
It works fine. I don't know why it doesn't work in the first example?
really thanks for any advice.
Global variables don't trigger pattern matching so you shouldn't use them in the condition of a rule unless the value is never changed. If you use a fact to represent the lock, the rules will execute for as many cycles as you specify:
(deftemplate lock
(slot value))
(deftemplate counter
(slot number))
(deffacts initial_data
(counter (number 0))
(lock (value 0))
)
(defrule set_counter
?f <- (counter (number ?x))
?l <- (lock (value 0))
=>
(modify ?l (value 1))
(printout t "plus 1" crlf)
(modify ?f (number (+ ?x 1)))
)
(defrule show_result
?f <- (counter (number ?x))
?l <- (lock (value 1))
=>
(printout t "the counter value has been changed:" crlf)
(ppfact (fact-index ?f) t)
(modify ?l (value 0))
)

Resources