JessTab: Can we count all subclass instances? - protege

I have a class A which consists of two subclasses B and C. Class B has three instances, while C two. Can I write a JessTab rule which will count all implicit instances of A i.e. give me 5?
Mapping class A in Jess:
(mapclass http...#A)
Rule to count instances which gives me 0 since there are no direct instances of A:
Originally:
(defrule countAinstances
?c <- (accumulate (bind ?count 0)
(bind ?count (+ ?count 1))
?count
(object (ís-a http...#A))
)
=>
(printout t ?c " number of class A instances." crlf))
This doesn't count instances of subclasses of A.
Modified version:
(defrule countAinstances
?c <- (accumulate (bind ?count 0)
(bind ?count (+ ?count 1))
?count
(object (OBJECT ?x&:(instanceof ?x http...#A)))
)
=>
(printout t ?c " number of class A instances." crlf))
The following error appears:
Jess reported an error in routine instanceof while executing
(instanceof ?_20_x(0,2,-1) http...#A) while executing rule LHS (TEQ)
while executing rule LHS (TECT). Message: Class not found:
http...#A. Program text: ( defrule countAinstances ?c <- (
accumulate ( bind ?count 0 ) ( bind ?count ( + ?count 1 ) ) ?count (
object ( OBJECT ?x & : ( instanceof ?x http...#A ) ) ) ) = > (
printout t ?c " number of class A instances." crlf ) ) at line 20.
Nested exception is: http...#A

Access the object and rely on Jess' own function instanceof, not the protege slot is-a:
(object (OBJECT ?x&:(instanceof ?x A)))
Use the full class name if A isn't imported.
if you don't have the Java class name, you'll have to test for all classes and subclasses in that pattern, using an (or) function. Rather tedious.
Later
Seeing that is-a contains class references that can be compared to class names, this would be the simplest way of writing the rule:
defrule countAinstances
?c <- (accumulate (bind ?count 0)
(bind ?count (+ ?count 1))
?count
(object (is-a ?x&B|C))
)
=>
(printout t ?c " number of subclass instances." crlf))

The complete solution-rule is as follows:
(defrule countAinstances
?c <- (accumulate (bind ?count 0)
(bind ?count (+ ?count 1))
?count
(object (is-a ?x&:(or (= ?x B)(= ?x C))))
)
=>
(printout t ?c " number of subclass instances." crlf))

Related

Clips Beginner: How to assign two variables to one template slot value without using multislot in pyclips

I want to insert two variable values in a string slot of a template but I am having errors. I know about the multislot but it is giving me a dictionary output like this:
('1.', '§ 2 is amended as follows:')
But I want like this:
1. § 2 is amended as follows:
https://www.csee.umbc.edu/portal/clips/usersguide/ug4.html In this link it is written that we can assign many variables to one slot in assert but when I do this I am getting errors. I am importing clips in python in VSCode. Thank you in advance and I hope I am explaining the issue properly.
These are the rules:
(defrule createlist1
(declare (salience 91))
(ROW (counter ?A)
(ID ?id)
(Text ?t)
(Path "//Document/Sect[3]/Sect/L/LI/Lbl"))
=>
(assert (Temp (tempvalue "YES")
(temptext ?t))))
(defrule createlist2
(declare (salience 91))
(and (Temp (tempvalue "YES")
(temptext ?t))
(ROW (counter ?A)
(ID ?id)
(Text ?text)
(Path "//Document/Sect[3]/Sect/L/LI/LBody/ParagraphSpan")))
=>
(printout t " value is " ?t ?text crlf)
(assert (WordPR (counter ?A)
(structure ?id)
(tag "list")
(style "list")
(text ?t ?text))))
These are the templates:
template_WordPR = """
(deftemplate WordPR
(slot counter (type INTEGER))
(slot structure (type INTEGER))
(slot tag (type STRING))
(slot style (type STRING))
(slot text (type STRING)))
"""
template_temporary = """
(deftemplate Temp
(slot tempvalue (type STRING))
(slot temptext (type STRING)))
"""
template_string = """
(deftemplate ROW
(slot counter (type INTEGER))
(slot ID (type INTEGER))
(slot Text (type STRING))
(slot Path (type STRING)))
"""
This is the error I am getting:
ERROR: The single field slot 'text' can only contain a single field value.
You can't put multiple values into a slot without declaring it as a multislot, but if you're dealing with strings you can concatenate the values before assigning them to the slot.
CLIPS>
(deftemplate WordPR
(slot counter (type INTEGER))
(slot structure (type INTEGER))
(slot tag (type STRING))
(slot style (type STRING))
(slot text (type STRING)))
CLIPS>
(deftemplate Temp
(slot tempvalue (type STRING))
(slot temptext (type STRING)))
CLIPS>
(deftemplate ROW
(slot counter (type INTEGER))
(slot ID (type INTEGER))
(slot Text (type STRING))
(slot Path (type STRING)))
CLIPS>
(deffacts start
(Temp (tempvalue "YES")
(temptext "1."))
(ROW (Text "§ 2 is amended as follows:")))
CLIPS>
(defrule createlist2
(declare (salience 91))
(Temp (tempvalue "YES")
(temptext ?t))
(ROW (counter ?A)
(ID ?id)
(Text ?text))
=>
(assert (WordPR (counter ?A)
(structure ?id)
(tag "list")
(style "list")
(text (str-cat ?t " " ?text)))))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-1 (Temp (tempvalue "YES") (temptext "1."))
f-2 (ROW (counter 0) (ID 0) (Text "§ 2 is amended as follows:") (Path ""))
f-3 (WordPR (counter 0) (structure 0) (tag "list") (style "list") (text "1. § 2 is amended as follows:"))
For a total of 3 facts.
CLIPS>

scheme - string-appends wrong type to apply error

I have this code
(lambda (symbol)
(let*(
(datalist (get-list symbol))
(desc " ")
(html "<table border=\"1\">")
(html (string-append html "<tr><td>" (list-ref datalist 1) "</td><t\
r><td>" (list-ref datalist 2) "</td></tr>"))
)
(do ((p 7 (+ 7 p)))
((> p (-(length datalist) 2)))
(desc (string-append desc "<tr><td>"(list-ref datalist p) "</td><td>"\
(list-ref datalist (+ p 1))"</td></tr>"))
)
(set! html (string-append html desc "</table>"))
html
)
)
I'm basically taking some elements from a datalist and adding some html tags to them. However, when I run the code, I get a "wrong type to apply error" on the desc binding (line 4). What gives? Even when i change it to values such as "foo", i still get the wrong type error.
Any suggestions?
The error is not in the binding, is in the loop's body:
(desc (string-append desc …))
You're trying to apply desc as if it were a procedure - but it's a string. So basically that part of the code is doing something equivalent to this:
("s1" "s2")
Which will result in the reported error. Perhaps you meant to do this?
(set! desc (string-append desc …))
I'll take a guess to figure out what were you trying to implement. And do notice how properly indenting and formatting the code helps to make it clear:
(lambda (symbol)
(let* ((desc " ")
(datalist (get-list symbol))
(html (string-append "<table border=\"1\">"
"<tr><td>"
(list-ref datalist 1)
"</td><tr><td>"
(list-ref datalist 2)
"</td></tr>")))
(do ((p 7 (+ 7 p)))
((> p (- (length datalist) 2)))
(set! desc (string-append desc
"<tr><td>"
(list-ref datalist p)
"</td><td>"
(list-ref datalist (+ p 1))
"</td></tr>")))
(string-append html desc "</table>")))

CLIPS constant compiler directive

Similar to the compiler directive for constants in C, is there a way I can do the following in CLIPS?
#define INFINITY 1000000000
(deftemplate foo
(slot num (type INTEGER) (default INFINITY))
)
...
(defrule bar
(foo (num INFINITY))
=>
...
)
You can define a global variable and treat it as a constant:
CLIPS> (defglobal ?*INFINITY* = 1000000000)
CLIPS>
(deftemplate foo
(slot num (type INTEGER) (default ?*INFINITY*)))
CLIPS>
(defrule bar
(foo (num ?num&:(eq ?num ?*INFINITY*)))
=>)
CLIPS> (assert (foo))
<Fact-1>
CLIPS> (facts)
f-0 (initial-fact)
f-1 (foo (num 1000000000))
For a total of 2 facts.
CLIPS> (agenda)
0 bar: f-1
For a total of 1 activation.
CLIPS>

Access a slot from multifield in deffunction

I have this function which calculates some value based on multiple slots of multiple multifield facts.
Because quite some slots are involved and all of them are needed in the function I was thinking if I could pass a whole fact to a function and access its slots in it,
like so:
(deftemplate a-fact
(slot id)
(slot name)
(slot ...)
...
)
(deffunction a-funciton (?factadr)
(switch ?factadr:name
(case bla then ...)
)
(return ?calculated-value)
)
(defrule a-rule
?factadr <- (a-fact (id ?i))
=>
(if (> **(a-function ?factadr) 20) then ... )
)
I saw this ?fact-adrres:slot-name in this example and thought it will work but it doesn't. So, is it possible and how to do it?
(bind ?facts (find-all-facts ((?f attribute))
(and (eq ?f:name wine)
(>= ?f:certainty 20))))
Clips 6.3 is used.
Use the fact-slot-value function.
CLIPS>
(deftemplate a-fact
(slot id)
(slot name))
CLIPS>
(defrule a-rule
?f <- (a-fact)
=>
(printout t (fact-slot-value ?f id) " " (fact-slot-value ?f name) crlf))
CLIPS> (assert (a-fact (id 3) (name x)))
<Fact-1>
CLIPS> (assert (a-fact (id 7) (name y)))
<Fact-2>
CLIPS> (run)
7 y
3 x
CLIPS>

Clips matching expression is not working

hello in clips i have this template:
(deftemplate cell(slot x)(slot y)(slot alive))
and this fact :
(start 1 1)
then i have this claus in the LHS :
?start<-(start ?x ?y)
and i want to get the variable ?a1
(cell (x (+ ?x 1) )(y ?y)(alive ?a1))
it seems that it's not allowed to add to the variable "(+ ?x 1)" so how
can i achieve what i want.
CLIPS> (deftemplate cell (slot x) (slot y) (slot alive))
CLIPS>
(deffacts initial
(start 1 1)
(cell (x 2) (y 1) (alive yes)))
CLIPS>
(defrule example
(start ?x ?y)
(cell (x =(+ ?x 1)) (y ?y) (alive ?a1))
=>
(printout t "?a1 = " ?a1 crlf))
CLIPS> (reset)
CLIPS> (run)
?a1 = yes
CLIPS>

Resources