CLIPS using variable as a name of instance - clips

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>

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.

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>

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>

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>

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