CLIPS deffacts and deftemplates for a family - clips

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.

Related

CLIPS using variable as a name of instance

can I use variable as a name of instance?
Example:
(make-instance [?input] (name)(age))
The name slot of an instance is predefined and stores the instance name, so when creating an instance you wouldn't specify it twice using the make-instance function. Otherwise, here's the syntax for using a variable to specify an instance name:
CLIPS (6.31 6/12/19)
CLIPS>
(defclass PERSON
(is-a USER)
(slot full-name)
(slot age))
CLIPS> (bind ?input p1)
p1
CLIPS>
(make-instance ?input of PERSON
(full-name "John Doe")
(age 23))
[p1]
CLIPS> (send [p1] print)
[p1] of PERSON
(full-name "John Doe")
(age 23)
CLIPS>

How do I constrain class slots to a certain class?

For example, I've the following:
(defclass ATTRIBUTE (is-a USER)
(slot name (type STRING))
(slot value (type INTEGER))
)
(defclass PROFILE (is-a USER)
(multislot skills (type ATTRIBUTE))
)
How should I change the above code to make it work?
The name slot is predefined for all classes, so you'll have to rename that slot in your ATTRIBUTE class to something else (such as attribute). Since message-handlers can dynamically change the value being assigned to a slot, you also need to enable dynamic constraint checking.
CLIPS (6.31 2/3/18)
CLIPS>
(defclass ATTRIBUTE
(is-a USER)
(slot attribute
(type STRING))
(slot value
(type INTEGER)))
CLIPS>
(defclass PROFILE
(is-a USER)
(multislot skill
(type INSTANCE)
(allowed-classes ATTRIBUTE)))
CLIPS> (set-dynamic-constraint-checking TRUE)
FALSE
CLIPS> (make-instance a1 of ATTRIBUTE)
[a1]
CLIPS> (make-instance p1 of PROFILE (skill 3))
[CSTRNCHK1] (3) for slot skill of instance [p1] found in put-skill primary in class PROFILE
does not match the allowed types.
[PRCCODE4] Execution halted during the actions of message-handler put-skill primary in class PROFILE
FALSE
CLIPS> (make-instance p1 of PROFILE (skill [a1]))
[p1]
CLIPS> (make-instance p2 of PROFILE (skill (instance-address [a1])))
[p2]
CLIPS> (defclass OTHER (is-a USER))
CLIPS> (make-instance o1 of OTHER)
[o1]
CLIPS> (make-instance p3 of PROFILE (skill [o1]))
[CSTRNCHK1] ([o1]) for slot skill of instance [p3] found in put-skill primary in class PROFILE
does not match the allowed classes.
[PRCCODE4] Execution halted during the actions of message-handler put-skill primary in class PROFILE
FALSE
CLIPS>

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))

Ignoring similar facts in Defrule 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))
)

Get slot value of an object

I need to retrieve a slot value (passing a slot name) from an instance which may contain other instances.
Example:
(defclass MAINCONTROLLER (is-a USER)
(slot uuid
(type STRING))
(slot param
(type INSTANCE))
(multislot zones
(type INSTANCE))
(slot state
(allowed-values a b c))
(slot pump
(allowed-values on off)))
(make-instance mainController of MAINCONTROLLER
(uuid "myController123")
(param [param-mainController])
(zones [zone1] [zone2])
(state a)
(pump on))
Slot named "param" contains an instance called [param-mainController].
CLIPS documentation suggests to retrieve a slot value with a send command with put- parameter.
I tried to use a generic function to retrieve a parameter only by passing the slotname.
(defmessage-handler USER get-param (?param-name)
(printout t "Slot value: " ?self:?param-name crlf))
But executing it I get:
(send [mainController] get-param state)
[MSGPASS2] No such instance mainController in function send.
FALSE
Some questions:
1) Do I need always to define a (create-accessor read) for every slot I need to read withsend command?
2) Could you please suggest some examples with best practices to retrieve a slot value from an instance?
Thank you,
Nic
By default, get- and put- handlers are created for slots. To retrieve specific slots use (send <instance> get-<symbol>) outside of a class's message-handlers and ?self:<symbol> within. To retrieve a slot where the slot name is stored in a variable, use (send <instance> (sym-cat get- <variable>)). Using ?self:<variable> is invalid syntax for slot shorthand references.
CLIPS> (clear)
CLIPS>
(defclass MAINCONTROLLER (is-a USER)
(slot uuid
(type STRING))
(slot param
(type INSTANCE))
(multislot zones
(type INSTANCE))
(slot state
(allowed-values a b c))
(slot pump
(allowed-values on off)))
CLIPS>
(defmessage-handler MAINCONTROLLER myprint ()
(printout t ?self:state crlf))
CLIPS>
(deffunction retrieve-slot (?ins ?slot-name)
(printout t (send ?ins (sym-cat get- ?slot-name)) crlf))
CLIPS>
(make-instance mainController of MAINCONTROLLER
(uuid "myController123")
(param [param-mainController])
(zones [zone1] [zone2])
(state a)
(pump on))
[mainController]
CLIPS> (send [mainController] get-state)
a
CLIPS> (send [mainController] myprint)
a
CLIPS> (retrieve-slot [mainController] state)
a
CLIPS>

Resources