Get values from a subClass in a sparql query - subclass

Im have a problem trying to do a sparql query using subClasses.
I have the following ontology:
where Quesos is a SubClassOf Ingrediente as you can see in the next image and Quesos have some other members too.
I want to have some recipes back from some ingredients. For example:
I want to have all the recipes that contains tomato, salt and cheese (where cheese could be any cheese) and I want to have back all the recipes than contains those ingredients.
Here is the problem: If i put the ingredient (like salt or tomato) then the query works fine, but if I put "Quesos" then I've got no answer. I donĀ“t know how to play with the subclasses in a sparql query.
So far I have the following query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rec:<http://www.receta.org#>
SELECT ?r ?cal ?tiempo ?dif (COUNT (?i) as ?cantIng)(GROUP_CONCAT(DISTINCT ?listaIngredientes) as ?listaIng)(GROUP_CONCAT(DISTINCT ?modoPreparacion) as ?Preparacion)
WHERE {
?x rdf:type rec:Receta .
?x rdfs:label ?r.
?x rec:Ingrediente rec:Sal.
?x rec:Ingrediente rec:Tomate.
?x rec:Calorias ?cal.
?x rec:tiempoPreparacion ?tiempo.
?x rec:dificultad ?dif.
?x rec:listaIngredientes ?listaIngredientes.
?x rec:modoPreparacion ?modoPreparacion.
}
GROUP BY ?r ?cal ?tiempo ?dif
ORDER BY ?cantIng
And I need to add the "subclassOf" line, but I cant find the way. Anyone can help? thank you!

This actually has nothing to do with subclasses, but just with the difference between an instance and a class. Since rec:Quesos is the class of all cheeses, and each specific type of cheese is modeled as an instance of rec:Quesos, you can query this by adding a graph pattern to your query that, instead of matching a specific ingredient (such as rec:Sal or rec:Tomate), matches any ingredient of the type rec:Quesos:
?x rec:Ingrediente ?i .
?i a rec:Quesos.
Or more shortly (since you don't actually need the value of ?i for anything else):
?x rec:Ingrediente [ a rec:Quesos ].

Related

How do I bind the value of a global variable to a slot?

I am trying to bind a slot to global variable but doesn't seem to work.
I have tried the below but the rules I created don't work.
*(defrule getusermalinfo
(user (usinfo ?usr))
=>
(bind ?usr ?*degreeofyes*)
)*
After, I want to use the slot value to make some decisions. Like the rule below:
*(defrule not-likely
(user {usinfo <= 10})
=>
(printout t "Not suffering from Kwashiorkor" crlf)
)*
One cannot use (bind) for modifying a fact's slot values. You need to use (modify), something like this:
(defrule getusermalinfo
?user <- (user)
=>
(modify ?user (usinfo ?*degreeofyes*))
)
Note, however, that you may have to add something to the LHS of this rule to select some specific user fact and/or avoid repeated firing of this rule after the modification.

How do I add a global variable to count the number of yes or no responses?

I am working on a nutrition diagnosis system where users are asked questions/symptoms and they respond by entering yes or no. I want to track the count of yes or no and make calculations with them. Like store the count of yes or no in global variables. I already have a function for the calculation but unsure how to capture the yes or no from the user input. I am new to using Jess rules. Below I have added codes of the working rule.
(defrule menu::initialize
(diagnosis)
=>
(assert
(question (ident q21) (text "Does the child's hair tend to be slight? (Yes or No)") (type yes-no))
(question (ident q22) (text "Does the child's hair tend to be reddish? (Yes or No)") (type yes-no))
(question (ident q23) (text "Is the child often affected by ISPA/ TBC? (Yes or No)") (type yes-no))
(question (ident q24) (text "Does the child's hair tend to be easily falls off? (Yes or No)") (type yes-no))
(question (ident q25) (text "Is there any abnormality on the child's complexion? (Yes or No)") (type yes-no))
(question (ident q26) (text "Is there any swelling on the child's face? (Yes or No)") (type yes-no))
)
(menu::init)
)
You have shown a rule called "menu::initialize" which inserts some facts called "question". You need a rule to fire on these facts, and this rule would then contain a statement to add 1 to a global variable. You can find examples for rules and for using global variables in the Jess manual.
Please don't expect someone on SO to do your homework for you.
I implemented the suggested solution above and got exactly what I was looking for.
My implementation below:.. Might not be an optimal solution but it works. Thanks SO :D
(defrule get-y21
"Add 1 to global variable for every yes answer from question21"
(answer (ident q21) (text yes ))
=>
(bind ?*countyes* (+ ?*countyes* 1))
)
(defrule get-n21
"Add 1 to global variable for every no answer from question21 "
(answer (ident q21) (text no ))
=>
(bind ?*countno* (+ ?*countno* 1))
)

What's the return value of CLIPS' do-for-fact if fact has been found?

The CLIPS reference manual explains about do-for-fact:
If a fact-set satisfies
the query, the specified action is executed, and the function is immediately terminated. The
return value is the evaluation of the action. If no fact-set satisfied the query, then the return value
is the symbol FALSE.
However, I cannot find any details on what the "evaluation of the action" means in general.
Is it safe to assume that do-for-fact always returns a value not equal to FALSE if a fact has been found?
Is the following code snippet correct?
(if (not (do-for-fact ((?p1 girl boy woman man)
(?p2 girl boy woman man)
(?p3 girl boy woman man))
(and (= ?p1:age ?p2:age ?p3:age)
(neq ?p1 ?p2)
(neq ?p1 ?p3)
(neq ?p2 ?p3))
(printout t ?p1:name " " ?p2:name " " ?p3:name crlf)))
then
(printout t "Nobody found" crlf)
)
Action refers to the BNF description of the function syntax:
(do-for-fact <fact-set-template> <query> <action>*)
This action term is the same term used in the body of a deffunction:
(deffunction <name> [<comment>]
(<regular-parameter>* [<wildcard-parameter>]) <action>*)
The return value in both cases is the last action evaluated. If the last action evaluated returns the value FALSE, then the do-for-fact function will return the value FALSE just as it would if there was no fact-set that satisfied the query.
In your example, the printout function has no return value which is treated as a non-FALSE value by the not function, so it will work as you expect
CLIPS> (printout t)
CLIPS> (not (printout t))
FALSE
CLIPS>
If you had included the symbol FALSE after the printout call, then the return value of the do-for-fact call would always be FALSE regardless of whether any fact-set satisfied the query.
(printout t ?p1:name " " ?p2:name " " ?p3:name crlf)
FALSE))

CLIPS (Expert System) write rules that add and remove values from the queue

I need help to write two rules, that add and remove values from queue. Rule that removes value from queue must use forall structure.
As far as I know, CLIPS does not have arrays, stack, lists or any other type of collections. So I have started with defining template queue with a slot item, that should represent value of a queue, but have not succeeded with the rules. Does anyone have any idea how this can be done?
CLIPS has multifield objects which act as lists.
You can define your queue as a global variable and modify it in your rules as for this example (LIFO queue).
CLIPS> (defglobal ?*queue* = (create$))
; add "foo" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "foo"))
("foo")
; add "bar" to the queue
CLIPS> (bind ?*queue* (insert$ ?*queue* 1 "bar"))
("bar" "foo")
; remove first element from the queue
(bind ?*queue* (delete$ ?*queue* 1 1))
("foo")

Scheme intersection between lists of pairs

I have the following example of lists where on the first line I have a result and on the second a filter, and I need to keep only the results that match at least one of the pairs in the filter.
(((john . ?x) (new-york . ?city)) ((mike . ?x) (chicago . ?city)) ((mary . ?x) (london . ?city)))
(((new-york . ?city)) ((chicago . ?city)))
(((john . ?x) (new-york . ?city)) ((mike . ?x) (chicago . ?city)) ((mary . ?x) (london . ?city)))
(((john . ?x) (air-hockey . ?game)) ((mike . ?x) (tennis . ?game)))
The problem I'm having is that both the results and filter have a variable number of parameters and I don't know how to take out one element at a time for comparison. I could use some hints since this is a homework.
Match would mean in the first example john and mike since their cities match the filter. While in the second example it would just add each of the games they play to the result.
While you have to check each of the entries on the first line, for the match to work you would have to get #t for at least one of the entries on the second line
It's not clear to me from your question what "match" means in this context. Let me suggest that you probably first want to develop a helper function that accepts one element from the first line and one element from the second line, and returns "true" when they match.
Also, I would definitely write some test cases first :).
I believe this is the same question that was asked here, take a look at my answer.

Resources