Writing a defrule that extends a deftemplate - clips

Suppose I have
(deftemplate a-template (slot A) (slot B))
and from an earlier rule I have A => C. I want to extend the template to
(deftemplate a-template (slot A) (slot B) (slot C))
How do you a write a rule that uses pre-existing rules to populate a fact template.
Thanks in advance

You can't redefine a deftemplate if any facts currently make use of that deftemplate:
CLIPS> (clear)
CLIPS> (deftemplate a-template (slot A) (slot B))
CLIPS> (deftemplate a-template (slot A) (slot B) (slot C))
CLIPS> (assert (a-template))
<Fact-1>
CLIPS> (deftemplate a-template (slot A) (slot B) (slot C) (slot D))
[CSTRCPSR4] Cannot redefine deftemplate a-template while it is in use.
ERROR:
(deftemplate MAIN::a-template
CLIPS>
However, if no such facts exist you can use introspection functions to examine the existing deftemplate in conjunction with the build function to create a new deftemplate:
CLIPS> (clear)
CLIPS>
(deffunction add-slot (?template ?slot)
(bind ?slots (deftemplate-slot-names ?template))
(if (member$ ?slot ?slots)
then
(return))
(bind ?build (str-cat "(deftemplate " ?template))
(progn$ (?s ?slots)
(if (deftemplate-slot-multip ?template ?s)
then
(bind ?build (str-cat ?build " (multislot " ?s ")"))
else
(bind ?build (str-cat ?build " (slot " ?s ")"))))
(bind ?build (str-cat ?build " (slot " ?slot ")"))
(bind ?build (str-cat ?build ")"))
(build ?build))
CLIPS> (deftemplate a-template (slot A) (slot B))
CLIPS> (ppdeftemplate a-template)
(deftemplate MAIN::a-template
(slot A)
(slot B))
CLIPS> (add-slot a-template C)
TRUE
CLIPS> (ppdeftemplate a-template)
(deftemplate MAIN::a-template
(slot A)
(slot B)
(slot C))
CLIPS>
If you wanted to redefine a template with existing facts, you'd need to save the existing facts using the save-facts function, retract all of them, redefine the template, and then reload the saved facts. This could cause rules matching the existing facts to be placed on the agenda if they had already executed.

Related

How to retrieve a handle to facts inside a deffacts construct?

As described by the question, I would somehow try to get an handle to a fact within a deffacts construct. The problem arises because I don't want to redefine the same thing several times in WM (since set-fact-duplication is true) and because I use a structured deftemplate in which a field is a FACT_ADDRESS.
You can't bind a fact address within a deffacts construct. What I would suggest instead is to use a symbolic link between the facts. In your case, if the name of the tourism-type, tourism-resort, and hotel facts is unique among facts of each type, you could use that slot as the symbolic link:
(deftemplate tourism-type
(slot name)
(slot score))
(deftemplate hotel
(slot name)
(slot tr)
(slot stars)
(slot price-per-night))
(deftemplate tourism-resort
(slot name)
(slot region)
(multislot type))
(deffacts the-tourism-type-list
(tourism-type (name culturale) (score 3))
(tourism-type (name enogastronomico) (score 4)))
(deffacts the-tourism-resort-list
(tourism-resort
(name Venezia)
(region Veneto)
(type culturale enogastronomico)))
(deffacts the-hotels-list
(hotel
(name hotel1)
(tr Venezia)
(stars 3)
(price-per-night 100)))
In your rules, you can then use the symbolic link to retrieve the linked fact:
(defrule food-and-wine-hotels
(hotel (name ?hotel)
(tr ?tr-name))
(tourism-resort
(name ?tr-name)
(type $? enogastronomico $?))
=>
(printout t ?hotel crlf))

I would like t o adjust my negative rule to accept any symbol and not just p and store that symbol in a variable

Hi i have created a clips program and in my defrule negative i am simulating a propositional law and would like the program to accept any symbol and not just a P symbol. I want the defrule to fire no matter the symbol that is there.
I have tried putting ?symbol instead of the P but that has not solved my problem just yet.
(deftemplate andprop (slot symbol1)(slot symbol2))
(deftemplate orprop (slot symbol1)(slot symbol2))
(deftemplate implies (multislot premise)(multislot implication))
(deftemplate sentence (multislot sent))
(defrule read-from-user
=>
(printout t "Please enter a sentence: Use ~ for not and => for implies please " crlf)
(bind ?response (readline))
(assert (sentence(sent ?response))))
(defrule negative
(sentence(sent "~(~P)"))
=>
(printout t "HI " crlf))
So i want the defrule negative to fire no matter the symbol that is in symbol so nt only if the symbol is a P
I'd suggest using the explode$ function to split the sentence into separate tokens.
CLIPS (6.31 2/3/18)
CLIPS>
(deftemplate andprop
(slot symbol1)
(slot symbol2))
CLIPS>
(deftemplate orprop
(slot symbol1)
(slot symbol2))
CLIPS>
(deftemplate implies
(multislot premise)
(multislot implication))
CLIPS>
(deftemplate sentence
(multislot sent))
CLIPS>
(defrule read-from-user
=>
(printout t "Please enter a sentence: Use ~ for not and => for implies please " crlf)
(bind ?response (readline))
(assert (sentence (sent (explode$ ?response)))))
CLIPS>
(defrule negative
(sentence (sent "~" "(" "~" ?symbol ")"))
=>
(printout t "HI " ?symbol crlf))
CLIPS> (run)
Please enter a sentence: Use ~ for not and => for implies please
~(~P)
HI P
CLIPS> (reset)
CLIPS> (run)
Please enter a sentence: Use ~ for not and => for implies please
~(~XYZ)
HI XYZ
CLIPS> (facts)
f-0 (initial-fact)
f-1 (sentence (sent "~" "(" "~" XYZ ")"))
For a total of 2 facts.
CLIPS>

Can I have a deptemplate inside a fact

(deftemplate andprop (slot symbol1)(slot symbol2))
(deftemplate orprop (slot symbol1)(slot symbol2))
(deftemplate implies (multislot premise)(multislot
implication))
(deftemplate sentence (multislot sent))
(defrule read-from-user
=>
(printout t "Please enter a value: " crlf)
(bind ?response (read))
(assert (sentence (sent andprop(symbol1 ?response)
(symbol2 ?response)))))
I am writing a CLIPS program to simulate the propsitional logic identities but when I try to run this piece of code i get the following
[EXPRNPSR3] Missing function declaration for 'symbol1'.
ERROR:
(defrule MAIN::read-from-user
=>
(printout t "Please enter a value: " crlf)
(bind ?response (read))
(assert (sentence (sent andprop (symbol1
You can set the value of a slot to another fact:
CLIPS (6.31 2/3/18)
CLIPS>
(deftemplate andprop
(slot symbol1)
(slot symbol2))
CLIPS>
(deftemplate orprop
(slot symbol1)
(slot symbol2))
CLIPS>
(deftemplate implies
(multislot premise)
(multislot implication))
CLIPS>
(deftemplate sentence
(multislot sent))
CLIPS>
(defrule read-from-user
=>
(printout t "Please enter a value: " crlf)
(bind ?response (read))
(bind ?sent (assert (andprop (symbol1 ?response)
(symbol2 ?response))))
(assert (sentence (sent ?sent))))
CLIPS> (run)
Please enter a value:
45678
CLIPS> (facts)
f-0 (initial-fact)
f-1 (andprop (symbol1 45678) (symbol2 45678))
f-2 (sentence (sent <Fact-1>))
For a total of 3 facts.
CLIPS>

correlation between deffunctions and defrules CLIPS

(deftemplate client
(slot idClient (type INTEGER))
(multislot nome)
(multislot birthdate)
(multislot registryCard)
(multislot endOfRegistryCard))
(deffunction reservation(?idfunc)
(build (str-cat"(defrule existsClient
(exists(client(idClient ?idfunc)))
=>
(printout t "exists" ?idfunc crlf))"
))
(run)
)
I made this deffunction and I want to see if exists the client with that idfunc that is received as parameter. what happens is that the defrule inside doesn't process this variable any thoughts how can i resolve?
I think you should set condition (assert your idfunc) and then fire the execution of your "existsClient" rule (defined as rule and not inside your function). That would be a clearer design in my opinion.
Typically you'll directly define your rules rather than using a deffunction, but here's how you can do it both ways:
CLIPS> (clear) ; Create rule and run with deffunction
CLIPS>
(deftemplate client
(slot idClient (type INTEGER))
(multislot nome)
(multislot birthdate)
(multislot registryCard)
(multislot endOfRegistryCard))
CLIPS>
(deffunction reservation (?idfunc)
(build (str-cat
"(defrule existsClient
(exists (client (idClient " ?idfunc ")))
=>
(printout t \"exists " ?idfunc "\" crlf))"))
(assert (client (idClient ?idfunc)))
(run))
CLIPS> (reservation 2)
exists 2
CLIPS> (ppdefrule existsClient)
(defrule MAIN::existsClient
(exists
(client (idClient 2)))
=>
(printout t "exists 2" crlf))
CLIPS> (clear) ; Create rule directly
CLIPS>
(deftemplate client
(slot idClient (type INTEGER))
(multislot nome)
(multislot birthdate)
(multislot registryCard)
(multislot endOfRegistryCard))
CLIPS>
(defrule existsClient
(exists (client (idClient 2)))
=>
(printout t "exists 2" crlf))
CLIPS> (ppdefrule existsClient)
(defrule MAIN::existsClient
(exists
(client (idClient 2)))
=>
(printout t "exists 2" crlf))
CLIPS> (assert (client (idClient 2)))
<Fact-1>
CLIPS> (run)
exists 2
CLIPS>

wxclips: [MSGFUN1] and [MSGPASS2] while trying to use instances

I'm trying to run classes in wxclips but its not working anyidea what's wrong.
Note this code is from tutorials and it should be working but it isn't
> CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write)) (slot bar))
> CLIPS> (make-instance a of A (foo 36)) [a] CLIPS> (make-instance b of A (bar 45)) [MSGFUN1]
> No applicable primary message-handlers found for put-bar. FALSE CLIPS>
> CLIPS>(defclass person (is-a USER) (multislot full-name) (role concrete) (slot gender (allowed-symbols male female)) (slot age))
> CLIPS>(definstances people (mike of person(gender "male")(age 24)))
> CLIPS>(send [mike] get-gender)
[MSGPASS2] No such instance mike in function send
You need to create slot accessors for any slot you want to read or write and instances from definstances are not created until you issue a (reset) command.
CLIPS> (defclass A (is-a USER) (role concrete) (slot foo(create-accessor write)) (slot bar (create-accessor write)))
CLIPS> (make-instance a of A (foo 36))
[a]
CLIPS> (make-instance b of A (bar 45))
[b]
CLIPS> (defclass person (is-a USER) (multislot full-name) (role concrete) (slot gender (allowed-symbols male female) (create-accessor read-write)) (slot age (create-accessor read-write)))
CLIPS> (definstances people (mike of person(gender "male")(age 24)))
CLIPS> (reset)
CLIPS> (send [mike] get-gender)
"male"

Resources