CLIPS: retrieve slot value from multislot if INSTANCES - clips

I have an object with a multislot of INSTANCE.
I have problems in getting instance's slot with one call.
Example:
(defclass AUTOMA (is-a USER)
(slot uuid))
(defclass TUTOMA (is-a USER)
(multislot list
(type INSTANCE)))
(make-instance A1 of AUTOMA
(uuid a1))
(make-instance A2 of AUTOMA
(uuid a2))
(make-instance T1 of TUTOMA
(list [a1] [a2]))
I want to retrive the first object uuid of the multislot list.
1) Try with "first$":
CLIPS> (first$ (send [T1] get-list))
([a1])
CLIPS> (send (first$ (send [T1] get-list)) get-uuid)
[MSGFUN1] No applicable primary message-handlers found for get-uuid.
FALSE
2) Try with "implode$":
CLIPS> (implode$ (first$ (send [T1] get-list)))
"[a1]"
CLIPS> (send (implode$ (first$ (send [T1] get-list))) get-uuid)
[MSGFUN1] No applicable primary message-handlers found for get-uuid.
FALSE
It seems that both ([a1]) and "[a1]" are not good for the (send XXX get-uuid) command.
Any suggestions, please?
Thank you
Nic

First$ returns a multifield value and implode$ returns a string. You need to use an instance name. Use nth$ to retrieve a field from within a multifield. You also need to keep the case used for your instance names consistent:
CLIPS>
(defclass AUTOMA
(is-a USER)
(slot uuid))
CLIPS>
(defclass TUTOMA
(is-a USER)
(multislot list (type INSTANCE)))
CLIPS> (make-instance A1 of AUTOMA (uuid a1))
[A1]
CLIPS> (make-instance A2 of AUTOMA (uuid a2))
[A2]
CLIPS> (make-instance T1 of TUTOMA (list [A1] [A2]))
[T1]
CLIPS> (send (nth$ 1 (send [T1] get-list)) get-uuid)
a1
CLIPS>

Related

CLIPS - How to relate 2 different deftemplates types when creating a defrule

I am using CLIPS 6.3 to develop a simple production management algorithm.
Currently I have a deftemplate for product orders and another one for product details.
(deftemplate orderSheets
(slot orderID (type INTEGER))
(slot orderDate (type INTEGER))
(slot product (type STRING))
(slot quantity (type INTEGER))
(slot deliverDate (type INTEGER))
)
(deftemplate productInfoSheets
(slot productID (type STRING))
(slot productStock (type INTEGER))
(slot prodTime (type INTEGER))
(slot maximumProduction (type INTEGER))
)
My doubt is how can I create a rule that relates the product order quantity (available in orderSheets) vs the available stock (available in productInfoSheets.
Thank you for your support,
Joan
Here's an example rule comparing order quantity to available stock:
(defrule not-enough
(orderSheets (quantity ?quantity))
(productInfoSheets (productStock ?stock))
(test (> ?quantity ?stock))
=>)

CLIPS LHS match multislot

I wrote this rule for an expert system :
(defrule wild chicory
(attribute (name habitat) (value sea montain grassland unknown))
=>
(assert (plant "Cichorium_Intybus"))
)
However I don't want the habitat's value to match all of the values that I have given, but to only match at least one of values.
I'm wondering how I should do this. I could do it so:
(defrule wild chicory
(or (attribute (name habitat) (value sea))
(attribute (name habitat) (value mountain))
(attribute (name habitat) (value grassland))
(attribute (name habitat) (value unknow))
)
=>
(assert (plant "Cichorium_Intybus"))
)
But I would like to know if there is a better solution. Thanks
If value is a single field slot, do it this way:
(defrule wild chicory
(attribute (name habitat) (value sea | mountain | grassland | unknown))
=>
(assert (plant "Cichorium_Intybus")))
If value is a multi field slot, do it this way:
(defrule wild chicory
(attribute (name habitat) (value $? sea | mountain | grassland | unknown $?))
=>
(assert (plant "Cichorium_Intybus")))

sparql delete query optimization

I have a query delete/insert that I'd like to optimize if possible. The query does delete/insert on up to 50 objects at a time. My Jmeter tests show that the DELETE clause takes 4 times longer in comparison to INSERT: delete takes around 3300 ms and insert takes about 860 ms. I'd like to improve the DELETE clause. I was thinking of using FILTER, but was told it would not scale well. Any recommendation is much appreciated.
What I have right now is:
DELETE {
?s ?p ?o.
?collection dc:identifier ?cid;
rdf:type ?ct;
rdf:li ?list.
?list rdf:first ?first;
rdf:rest ?rest.
}
WHERE
{
{ ?s dc:identifier "11111"^^xsd:int; ?p ?o. }
UNION { ?s dc:identifier "22222"^^xsd:int; ?p ?o.}
UNION {?s dc:identifier "33333"^^xsd:int; ?p ?o.}
UNION{} UNION{}.......
OPTIONAL{
?s dc:hasPart ?collection.
?collection dc:identifier ?cid;
rdf:type ?ct;
rdf:li ?list.
?list rdf:first ?first;
rdf:rest ?rest.
}
INSERT DATA
{
GRAPH <http://test.org/>
{.....}
GRAPH <http://test.org/>
{.....}
GRAPH....
}
Without having your data, or even knowing what triple store you're using, we can't really help much in optimization. It might just be that deletes are more expensive than insertions. That said, one thing that might help is to use values rather than unions in your where block. That is, instead of:
{ ?s dc:identifier "11111"^^xsd:int; ?p ?o. }
UNION { ?s dc:identifier "22222"^^xsd:int; ?p ?o.}
UNION {?s dc:identifier "33333"^^xsd:int; ?p ?o.}
UNION{} UNION{}.......
do:
values ?identifier { "11111"^^xsd:int "22222"^^xsd:int "33333"^^xsd:int "44444"^^xsd:int }
?s dc:identifier ?identifier ; ?p ? o

Accelerate SPARQL query - filtering out rows which contain

I am currently working with SPARQL (and TopBraidComposer). I have a query which only brings back matching literals, and then filters out the literals based on not wanting certain categories.
Currently, this query is taking a long time to run, and I think it is my FILTER which is causing the delay. I was wondering if someone would have a better and faster way of filtering out (NOT returning) rows which contain a set of key words (ex. cat1, cat2, cat3).
As of now, I am using;
SELECT ?category
WHERE {
?s1 ?p ?category .
?s2 ?p ?category .
FILTER (str(?category) != "Cat1") .
FILTER (str(?category) != "Cat2") .
FILTER (str(?category) != "Cat3") .
FILTER (str(?category) != "Cat4") .
FILTER (str(?category) != "Cat6") .
FILTER (str(?category) != "Cat8") .
}
It's not clear how much you've trimmed down your example, but the code you presented is doing more work than it needs to.
SELECT ?category
WHERE {
?s1 ?p ?category .
?s2 ?p ?category .
FILTER (str(?category) != "Cat1") .
FILTER (str(?category) != "Cat2") .
FILTER (str(?category) != "Cat3") .
FILTER (str(?category) != "Cat4") .
FILTER (str(?category) != "Cat6") .
FILTER (str(?category) != "Cat8") .
}
Suppose your data has
:a :p "Cat0" .
:b :p "Cat0" .
Then the bindings for ?s1, ?s2, ?p? and ?category can be
?s1 ?s2 ?p ?category
--------------------
:a :a :p "Cat0"
:a :b :p "Cat0"
:b :b :p "Cat0"
:b :a :p "Cat0"
That's four ways to select "Cat0". You said that you want literals, but right now you're hitting every kind of ?category and applying str to it multiple times. You might do this instead:
SELECT DISTINCT ?category
WHERE {
?s ?p ?category .
FILTER( isLiteral(?category) &&
!(str(?category) in ("Cat1", "Cat2", "Cat3",
"Cat4", "Cat6", "Cat8")) )
}

CLIPS: Multifield slots

I'm doing an exercise and where I need to create a simple dating agency matching system. Currently each person have one hobby, hobbies are categories by active and inactive and if the two hobbies match and the two persons have opposite sex, the dating agency thinks these to persons are a match.
So now I need the system to be able to allow for multiple hobbies but I cant seem to get my head around this.
Here's what I have:
(deftemplate MAIN::person
(slot name)
(slot age)
(multislot hobby)
(slot town)
(slot sex))
(person (name "Jane")
(age 25)
(hobby fashion gardening)
(town montrose)
(sex female))
(deffacts hobby_types "Hobby categories"
(hobby_type gardening active)
(hobby_type swinging active)
(hobby_type reading inactive)
(hobby_type fashion inactive)
)
(defrule compatible_hobbies
(opposite_sex ?name1 ?name2)
(person (name ?name1) (hobby ?hobby1))
(person (name ?name2) (hobby ?hobby2))
(hobby_type ?hobby1 ?type)
(hobby_type ?hobby2 ?type)
=>
(assert (hobbies_match ?name1 ?name2))
)
So first up, do I declare the multislot field correctly? And how do I adjust my compatible_hobbies rule to match against either of the hobbies that a person might have?
The multislot hobby in person is declared correctly. But your rule won't match the hobbies correctly and would match the same fact to the same fact showing that Jane is compatible with Jane. Actually if the rule matched facts it would generate the Cartesian product of the person facts (or a large number of non-desired matches).
I modified the rule to:
(defrule compatible_hobbies
(person (name ?n1) (hobby $? ?h1 $?))
(person (name ?n2) (hobby $? ?h1 $?))
(hobby_type ?h1 ?x)
(test (neq ?n1 ?n2))
=>
(assert (hobbies_compatible ?n1 ?n2))
)
So if you assert two person facts like
(person (name "Jane") (hobby blah1 gardening blah2)) and (person (name "Jim") (hobby blah3 gardening blah4)) then the rule will fire and the fact (hobbies_compatible Jim Jane) will be asserted (as well as the fact (hobbies_compatible "Jim" "Jane")).
The wildcard $? variable matches a set of symbols preceding and following the desired matching hobby. Your opposite sex fact should probably also be a test instead of a fact.

Resources