Forall statement applied for a subset of elements in PDDL Domain? - forall

Case of use
First of all, I want to explain my case of use: I want to divide a field in different sectors and all plants should be analyzed by robots (just one robot per sector). I want to check in :preconditions that all plants for one sector are already analyzed, so that the robot return to the 'home'.
Problem
Here is the domain PDDL. My problem is placed in the preconditions of "tracker-back-home" action. Now I am checking if all the plants have been already analyzed, but I need to know if all the plants of the specific sector ?s are analyzed. It is possible to do using forall statement?
(define (domain killbee)
(:requirements :strips :typing)
(:types
bee location - object
;Inheritance
tracker - bee
hive plant sector - location
)
(:predicates
(directly-connected ?l1 - location ?l2 - location)
(at ?l1 - object ?l2 - object) ;location is hive, plant or sector
(free-sector ?s - sector)
(bee-with-sector ?b - tracker)
(tracker-ready-to-move ?b - tracker)
(analyzed-plant ?p - plant ?s - sector)
(sector-tracked ?s - sector)
(plant-in-sector ?p - plant ?s - sector)
)
...
...
(:action tracker-back-home
:parameters (?b - tracker ?p - plant ?h - hive ?s - sector)
:precondition
(and (tracker-ready-to-move ?b)
(at ?b ?p)
(not (at ?b ?h))
(forall (?x - plant) (analyzed-plant ?x ?s)))
)
:effect
(and
(not (at ?b ?p))
(at ?b ?h)
(sector-tracked ?s)
(not (bee-with-sector ?b))
(free-sector ?s))
)...

Did you check out the language feature "imply" as defined by PDDL 2.1? (Maybe it was already defined before 2.1 -- not sure.) With it, you can define:
(forall (?pPrime - plant)
(imply (at ?s ?pPrime) (analyzed-plant ?pPrime ?s))
)
Note: I am not sure whether the order of parameters in (at ?s ?pPrime) is correct. It's supposed to encode that the plant ?pPrime is in sector ?s.
The condition expands to a large set of implications reading that for all plants p' (no matter where they are) holds: "if plant p' is in s, then it's analyzed in s". This should encode exactly what you are looking for.

Related

Counting SparQL subjects with certain properties without Nestation

I have a SparQL query which first gets me the subjects with one of two predicates.
Then, I group them by a third predicate (that can also be blank) and count the grouped contained subjects.
How (if possible) can I do this without nestation?
My Query currently looks like this:
SELECT ?d (COUNT(?a) AS ?aCount)
WHERE{
SELECT ?d ?a
WHERE {
?a ?b ?c
FILTER (?b=:x||?b=:y)
OPTIONAL {?a :z ?d}
}
GROUP BY ?a ?d
}
GROUP BY ?d
This works, as far as I know, but is with nestation.
Thanks!

SPARQL "Different Than"

Background
I have a graph database where nodes represent individual people and the edges are predicates hasMother and hasFather. I'd like to identify all of the nodes that share a mother, but don't share the same father.
Attempt
There are a few SPARQL terms that immediately pop into my mind when thinking about this problem. Namely Filter, != and NOT EXISTS.
I first set out and defined some sets...
Let M be the set of all winiks that have mother id, mother_id.
Let F be the set of all winiks that have father id, father_id.
The following query returns a qraph of M ∩ F.
PREFIX ex: <https://ex.com#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
CONSTRUCT WHERE {
?winik_id ex:hasMother ?mother_id.
?winik_id ex:hasFather ?father_id.
}
My hiccup is writing the exclusion part (its actually hard for me to verbalize the exact part I'm stuck on)-specifically how to deal with how general the query is (across all identifiers).
This should return pairs of people that have the same mother but different father.
SELECT ?p1 ?p2 WHERE {
?p1 ex:hasMother ?m .
?p1 ex:hasFather ?f .
?p2 ex:hasMother ?m .
?p2 ex:hasFather ?f2 .
FILTER (?f != ?f2)

Property paths in Sparql

I am posing a Sparql query to Dbpedia endpoint with property paths:
select (COUNT(distinct ?s2) AS ?count) WHERE{
?s2 skos:broader{0,2} dbc:Countries_in_Europe
}
I want to pose the same query without property paths:
select (COUNT(distinct ?s2) AS ?count) (COUNT(distinct ?s1) AS ?count1) WHERE{
?s2 skos:broader dbc:Countries_in_Europe.
?s1 skos:broader ?s2.
}
I have two questions:
Is it possible to get ?s1+?s2 for the second query?
For the second query, I expect the sum of the count numbers +1 (dbc:Countries_in_Europe) should be the same with the first query. But they are not. What is wrong?
Thanks in advance.
You're using non-standard SPARQL, i.e. restricting the depth did not make it to the final version, see the W3C specs
I guess the first query is supposed to returns sub-categories of the given one up to a depth 2, right? Your second query doesn't do the same. You have to use a UNION of each distance, i.e. one for the direct sub-categories, and one for the other levels.
SELECT (COUNT(distinct ?s) AS ?count) WHERE {
{
?s skos:broader dbc:Countries_in_Europe
} UNION {
?s1 skos:broader dbc:Countries_in_Europe.
?s skos:broader ?s1
}
}
Note, in your first query you used {0,2} which means due to 0 distance the category dbc:Countries_in_Europe itself is also part of the result. If you need it, you should add +1 to the result of the second query.
Update
As per #JohuaTaylor's comment below, a more compact syntax would be
SELECT (COUNT(distinct ?s) AS ?count) WHERE {
?s skos:broader/skos:broader? dbc:Countries_in_Europe
}

SPARQL if an instance has a property, others must as well

I have a specific instance and a SPARQL query that retrieves other instances similar to that one. By similar, I mean that the other instances have at least one common property and value in common with the specific instance, or have a class in common with the specific instance.
Now, I'd like to extend the query such that if the specific instance has a value for a "critical" property, then the only instances that are considered similar are those that also have that critical property (as opposed to just having at least one property and value in common).
For instance, here is some sample data in which instance1 has a value for predicate2 which is a subproperty of isCriticalPredicate.
#prefix : <http://example.org/rs#>
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
:instance1 a :class1.
:instance1 :predicate1 :instance3.
:instance1 :predicate2 :instance3. # (#) critical property
:instance2 a :class1.
:instance2 :predicate1 :instance3.
:instance4 :predicate2 :instance3.
:predicate1 :hasSimilarityValue 0.6.
:predicate2 rdfs:subPropertyOf :isCriticalPredicate.
:predicate2 :hasSimilarityValue 0.6.
:class1 :hasSimilarityValue 0.4.
Here is a query in which ?x is the specific instance, instance1. The query retrieves just instance4, which is correct. However, if I remove the critical property from instance1 (line labeled with #), I get no results, but should get instance2, since it has a property in common with instance1. How can I fix this?
PREFIX : <http://example.org/rs#>
select ?item (SUM(?similarity * ?importance * ?levelImportance) as ?summedSimilarity)
(group_concat(distinct ?becauseOf ; separator = " , ") as ?reason) where
{
values ?x {:instance1}
bind (4/7 as ?levelImportance)
{
values ?instanceImportance {1}
?x ?p ?instance.
?item ?p ?instance.
?p :hasSimilarityValue ?similarity
bind (?p as ?becauseOf)
bind (?instanceImportance as ?importance)
}
union
{
values ?classImportance {1}
?x a ?class.
?item a ?class.
?class :hasSimilarityValue ?similarity
bind (?class as ?becauseOf)
bind (?classImportance as ?importance)
}
filter (?x != ?item)
?x :isCriticalPredicate ?y.
?item :isCriticalPredicate ?y.
}
group by ?item
I've said it before and I'll say it again: minimal data is very helpful. From your past questions, I know that your working project has similarity values on properties and the like, but none of that really matters for the problem at hand. Here's some data that just has a few instances, property values, and one property designated as critical:
#prefix : <urn:ex:>
:p a :criticalProperty .
:a :p :u ; #-- :a has a critical property, so
:q :v . #-- only :d can be similar to it.
:c :q :v ; #-- :c has no critical properties, so
:r :w . #-- both :a and :d can be similar to it.
:d :p :u ;
:q :v .
The trick in a query like this is to filter out the results that have the problem, not to try to select the ones that don't. Logically, those mean the same thing, but in writing the query, it's easier to think about constraint violation, and to try to filter out the results that violate the constraint. In this case, you want to filter out any results where the instance has a critical property and value but the similar instance doesn't.
prefix : <urn:ex:>
select ?i (group_concat(distinct ?j) as ?js) where {
#-- :a has a critical property, but
#-- :c does not, so these are useful
#-- starting points
values ?i { :a :c }
#-- get ?j instances that have a value
#-- in common with ?i.
?i ?property ?value .
?j ?property ?value .
#-- make sure that ?i and ?j aren't
#-- the same instance
filter (?i != ?j)
#-- make sure that there is no critical
#-- property value that ?i has that
#-- ?j does not also have
filter not exists {
?i ?criticalProperty ?criticalValue .
?criticalProperty a :criticalProperty .
filter not exists {
?j ?criticalProperty ?criticalValue .
}
}
}
group by ?i
----------------------------
| i | js |
============================
| :a | "urn:ex:d" |
| :c | "urn:ex:d urn:ex:a" |
----------------------------
Related
There are some other questions that also touch on constaint satisfaction/violation that might be useful reading. While not all of these use nested filter not exists, most of them do have a pattern of filter not exists { … filter <negative condition> }.
Find lists containing ALL values in a set? (This actually uses a nested filter not exists.)
Is it possible to express a recursive definition in SPARQL?
Count values that satisfy a constraint and return 0 for those that don't satisfy it in SPARQL
SPARQL: return all intersections fulfilled by specified or equivalent classes (There's another nested filter not exists, in the last query in the answer.)

Finding linked topics in DBPedia using SPARQL

Consider we have these two topics:
http://dbpedia.org/page/Jason_Furman
and
http://dbpedia.org/page/London
For the first topic, Jason Furman, we can see on the property almaMater that he went to:
http://dbpedia.org/page/London_School_of_Economics
And looking at London School of Economics we see that it has London as value of the city property.
So my question is:
If we have two topics, A and B, how can we find property values of A that has topic B in any of it's properties?
select distinct ?a ?p ?y ?q ?b where {
values ?a { dbpedia:Jason_Furman }
values ?b { dbpedia:London }
?a ?p ?y .
?y ?q ?b .
}
SPARQL results
(Note that there are two results because there are two such properties: dbpprop:almaMater and dbpedia-owl:almaMater.)