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"
Related
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))
(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>
(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>
Is there any way to get the objects in clips in order on LHS side based on a particular slot in class?
(defclass SAMPLE
"all the information about students"
(is-a BASE_SAMPLE) (role concrete) (pattern-match reactive)
(slot ID (create-accessor read-write) (access initialize-only) (propagation inherit) (visibility public) (type INTEGER))
(slot NAME (create-accessor read-write) (access initialize-only) (propagation inherit) (visibility public) (type STRING))
)
if I have 100 SAMPLE objects, and I want all of them to come in ascending order based on the slot ID on the LHS of a rule, is this poosilbe in clips?
There's two ways you can sort the objects. You can do it on the LHS by adding some additional information to either the objects or a separate fact/instance to retain information on which objects have been processed:
CLIPS> (clear)
CLIPS>
(defclass STUDENT
(is-a USER)
(slot id)
(slot full-name)
(slot processed (default no)))
CLIPS>
(definstances people
(of STUDENT (id 102) (full-name "Fred Jones"))
(of STUDENT (id 438) (full-name "Sally Smith"))
(of STUDENT (id 391) (full-name "John Farmer")))
CLIPS>
(defrule list
?i <- (object (is-a STUDENT)
(id ?id1)
(processed no))
(not (object (is-a STUDENT)
(id ?id2&:(> ?id1 ?id2))
(processed no)))
=>
(modify-instance ?i (processed yes))
(printout t ?id1 " " (send ?i get-full-name) crlf))
CLIPS> (reset)
CLIPS> (run)
102 Fred Jones
391 John Farmer
438 Sally Smith
CLIPS>
Or you can sort the values on the RHS:
CLIPS> (clear)
CLIPS>
(defclass STUDENT
(is-a USER)
(slot id)
(slot full-name))
CLIPS>
(definstances students
(of STUDENT (id 102) (full-name "Fred Jones"))
(of STUDENT (id 438) (full-name "Sally Smith"))
(of STUDENT (id 391) (full-name "John Farmer")))
CLIPS>
(deffunction id-sort (?i1 ?i2)
(> (send ?i1 get-id) (send ?i2 get-id)))
CLIPS>
(defrule list
=>
(bind ?instances (find-all-instances ((?i STUDENT)) TRUE))
(bind ?instances (sort id-sort ?instances))
(progn$ (?i ?instances)
(printout t (send ?i get-id) " " (send ?i get-full-name) crlf)))
CLIPS> (reset)
CLIPS> (run)
102 Fred Jones
391 John Farmer
438 Sally Smith
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.