Reputation: 3
I would greatly appreciate some assistance with my CLIPS project.
Okay so I'm attempting to create a dog breed adviser. The deftemplate looks like this:
(deftemplate breed
(multislot name)
(slot size)
(slot type-owner)
(slot Living_Space)
(slot children)
(slot grooming)
(slot exercise)
(slot noisiness)
(slot trainability)
(slot aggression)
(slot playfulness)
(slot excitability)
(slot score))
A deffacts looks like this:
(deffacts dog-breeds
(breed (name Great_Dane)
(size 5)
(type-owner No)
(Living_Space 5)
(children 5)
(grooming 1)
(exercise 4)
(noisiness 2)
(trainability 1)
(aggression 2)
(playfulness 2)
(excitability 3)
(score 0))
So I write two types of defrules: one retracts facts that do not meet the (user specified) criteria and the other type increments the "score" value every time the fact meets the criteria. Only a few rules retract, so it's important for me to get the increment rules working. The user input and criteria for each slot can be from 1 to 5.
My question is: how do I change the following code without going into an infinite loop? At the end I want to seek out the fact with the maximum score and display it.
(defrule children
(input 1)
?children <- (breed (name ?)(size ?)(type-owner ?)(Living_Space ?) (children 1|2)(grooming ?)(exercise ?)(noisiness ?)
(trainability ?)(aggression ?)(playfulness ?)(excitability ?)(score ?score)
=>
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc))
Upvotes: 0
Views: 897
Reputation: 10757
If the sole purpose of the (input 1) fact is to increment the score and is no longer needed after the score is incremented, just retract that fact.
(defrule children
?f <- (input 1)
?children <- (breed (children 1|2) (score ?score))
=>
(retract ?f)
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc)))
Note that I've removed all of the slots from the pattern containing the ? wildcard as these are unnecessary.
If the (input 1) fact is needed by other rules, you can create an intermediate fact that can be retracted.
(defrule create-intermediate
(input 1)
=>
(assert (increment)))
(defrule children
?f <- (increment)
?children <- (breed (children 1|2) (score ?score))
=>
(retract ?f)
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc)))
You could also track what you've scored within the fact. Add a (multislot scored) to your breed deftemplate and then you can do this:
(defrule children
(input 1)
?children <- (breed (children 1|2) (score ?score) (scored $?scored))
(test (not (member$ children ?scored)))
=>
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc) (scored children ?scored)))
Finally, object patterns do not retrigger when slots are changed that are not present in the pattern. So if you used defclasses instead of deftemplates, you could do this:
(defrule children
(input 1)
?children <- (object (is-a BREED) (children 1|2))
=>
(bind ?sc (+ (send ?children get-score) 1))
(send ?children put-score ?sc))
Upvotes: 0