Ignoring similar facts in Defrule CLIPS - clips

I'm trying to create a family tree program using CLIPS.
I'm very new to CLIPS and am facing difficulty with some operations in one of the defrule I have created.
The operation I'm trying to perform is to create facts for children who are siblings of each other. So for each pair of children, I expect the program to generate 2 new siblings facts. But the program seems to generate 4 - it's also listing each child as its own sibling...
I tried googling for a solution, but I couldn't figure out how to ask the computer to not fire if(?cn == ?sn).
Can someone please help?
(deftemplate siblings
(slot subject-name)
(slot sibling-name)
)
(defrule set-siblings
(child
(child-name ?cn)
(parent-name ?p))
(child
(child-name ?sn)
(parent-name ?p))
=>
(assert (siblings
(subject-name ?cn)
(sibling-name ?sn))
)

Modify your second pattern so that the child name matched must be different than the name bound in the first pattern:
(defrule set-siblings
(child
(child-name ?cn)
(parent-name ?p))
(child
(child-name ?sn&~?cn)
(parent-name ?p))
=>
(assert (siblings
(subject-name ?cn)
(sibling-name ?sn))
)

Related

CLIPS deffacts and deftemplates for a family

First time trying CLIPS in the last few days and must admit it's a little overwhelming. I am at this exercise in the Giarratano book:
"Convert the following sentences to facts in a deffacts statement. For each group of related facts, define a deftemplate that describes a more general relationship.
The father of John is Tom.
The mother of John is Susan.
The parents of John are Tom and Susan.
Tom is a father.
Susan is a mother.
John is a son.
Tom is a male.
Susan is a female.
John is a male.
So I have tried the following:
(deftemplate father-of
(slot father)
(slot child)
)
(deftemplate mother-of
(slot mother)
(slot child)
)
(deftemplate parents-of
(slot mother)
(slot father)
(slot child)
)
(deftemplate male
(slot person)
)
(deftemplate female
(slot person)
)
(deftemplate father
(slot person)
)
(deftemplate mother
(slot person)
)
(deftemplate son
(slot person)
)
(deftemplate male
(slot person)
)
(deftemplate female
(slot person)
)
(deffacts family
(father-of (father Tom) (child John))
(mother-of (mother Susan) (child John))
(parents-of (mother Susan) (father Tom) (child John))
(father (person Tom))
(mother (perosn Susan))
(son (person John))
(male (person Tom))
(female (person Susan))
(male (person John))
)
When loading into CLIPs, it returns
CLIPS> (load familyy.clp)
Defining deftemplate: father-of
Defining deftemplate: mother-of
Defining deftemplate: parents-of
Defining deftemplate: male
Defining deftemplate: female
Defining deftemplate: father
Defining deftemplate: mother
Defining deftemplate: son
Defining deffacts: family
TRUE
Is this good? Like it works? I have a bunch of this exercises that I want to do, but does TRUE mean that it's done correctly? What does all the "redefining template mean"
Also if you have any places with examples or anything regarding clips, it's highly appreciated, as I noticed CLIPS resources are kind of slim and hard to find.
You can download CLIPS related material from here: https://sourceforge.net/projects/clipsrules/
In addition to the documentation that can be downloaded, you can also view it online here: http://www.clipsrules.net/Documentation.html
From the documentation for the load command:
Loads the constructs stored in the file specified by into the environment. If the compilations item is being watched (see section 13.2), then an informational message (including the type and name of the construct) will be displayed for each construct loaded. If the compilations item is not being watched, then a character is printed for each construct loaded (“*” for defrule, “$” for deffacts, “%” for deftemplate, “:” for defglobal, “!” for deffunction, “^” for defgeneric, “&” for defmethod, “#” for defclass, “~” for defmessage-handler, “#” for definstances, and “+” for defmodule). This function returns TRUE if the file was successfully loaded, otherwise FALSE is returned.

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: One-time pattern matching a value of a multislot

I read in this SO answer that
When an instance is created or deleted, all patterns applicable to
that object are updated. However, when a slot is changed, only those
patterns that explicitly match on that slot are affected.
Now I have the following problem:
I have a multislot that receives more and more items over time.
I have a rule R1 that fires if "some_value" is contained in the multislot. When I add "some_value" to the multislot everything works as expected. However, if I add another item, say "another_value" to the multislot, R1 fires again. This is consistent to what I cited above, but it is not what I want. I want R1 to fire only once if "some_value" is contained in the multislot, and I don't want R1 to fire again if another value is added to the multislot.
How can I do that?
I could use many slots instead of a multislot, but this would not work in case I don't know the number of possible values.
If you can't assign the values to different slots--which is how you'd normally handle firing rules on selected changes--then you need to track which changes have been processed. Tracking either the rules or values that have been processed would be the most straightforward way to do this. If each rule processes just one value, then tracking the rules would be better so that you could have multiple rules triggered for the same value change. Here's an example where rules R1 and R2 are restricted to a single change and rule R3 exhibits the behavior you're currently experiencing:
CLIPS> (clear)
CLIPS>
(defclass XAMPL
(is-a USER)
(multislot properties)
(multislot processed))
CLIPS>
(definstances initial
([x1] of XAMPL))
CLIPS>
(defrule add_some_value
(declare (salience -1))
?o <- (object (name [x1])
(properties $?p&:(not (member$ some_value ?p))))
=>
(modify-instance ?o (properties some_value ?p)))
CLIPS>
(defrule add_another_value
(declare (salience -2))
?o <- (object (name [x1])
(properties $?p&:(not (member$ another_value ?p))))
=>
(modify-instance ?o (properties another_value ?p)))
CLIPS>
(defrule R1
?o <- (object (name [x1])
(properties $?properties&:(member$ some_value ?properties))
(processed $?processed&:(not (member$ R1 ?processed))))
=>
(modify-instance ?o (processed ?processed R1))
(printout t "Rule R1 fires" crlf))
CLIPS>
(defrule R2
?o <- (object (name [x1])
(properties $?properties&:(member$ some_value ?properties))
(processed $?processed&:(not (member$ some_value ?processed))))
=>
(modify-instance ?o (processed ?processed some_value))
(printout t "Rule R2 fires" crlf))
CLIPS>
(defrule R3
(object (name [x1])
(properties $?properties&:(member$ some_value ?properties)))
=>
(printout t "Rule R3 fires" crlf))
CLIPS> (reset)
CLIPS> (run)
Rule R2 fires
Rule R1 fires
Rule R3 fires
Rule R3 fires
CLIPS>

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