I'd like to identify all individuals, that have the same properties as some other individuals. Imagine having different shopping lists with different items on them one can either buy or rent (object properties). To make things more complex, I also want to pay an exact amount for the parking and travel a certain distance (data properties). At the same time, there exist different stores offering different items. Being a lazy person, I would like to identify the stores for each list, that offer all the items on the list.
I believe this is a generalization of this question but I somehow cannot wrap my head around how to do this.
I created some sample individuals:
@prefix : <http://www.shopping.org/model#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www.shopping.org/model> .
<http://www.shopping.org/model> rdf:type owl:Ontology .
# Object Properties
:buy rdf:type owl:ObjectProperty .
:rent rdf:type owl:ObjectProperty .
# Data properties
:distance rdf:type owl:DatatypeProperty .
:parking rdf:type owl:DatatypeProperty .
# Classes
:Product rdf:type owl:Class .
:ShoppingList rdf:type owl:Class .
:Store rdf:type owl:Class .
# Individuals
:Apples rdf:type owl:NamedIndividual ,
:Product .
:Cereal rdf:type owl:NamedIndividual ,
:Product .
:List1 rdf:type owl:NamedIndividual ,
:ShoppingList ;
:buy :Apples ,
:Milk ;
:distance "9.0"^^xsd:float ;
:parking "10.0"^^xsd:float .
:List2 rdf:type owl:NamedIndividual ,
:ShoppingList ;
:buy :Cereal ,
:Milk ;
:rent :TV ;
:distance "5.0"^^xsd:float ;
:parking "10.0"^^xsd:float .
:Milk rdf:type owl:NamedIndividual ,
:Product .
:Store1 rdf:type owl:NamedIndividual ,
:Store ;
:buy :Apples ,
:Cereal ,
:Milk ,
:TV ;
:distance "9.0"^^xsd:float ;
:parking "10.0"^^xsd:float .
:Store2 rdf:type owl:NamedIndividual ,
:Store ;
:buy :Cereal ,
:Milk ;
:rent :TV ;
:distance "5.0"^^xsd:float ;
:parking "10.0"^^xsd:float .
:TV rdf:type owl:NamedIndividual ,
:Product .
# General axioms
[ rdf:type owl:AllDisjointClasses ;
owl:members ( :Product
:ShoppingList
:Store
)
] .
and also tried some first queries. This is the best I have:
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 : <http://www.shopping.org/model#>
SELECT DISTINCT ?list ?store ?prop
WHERE {
?list a :ShoppingList .
?store a :Store .
?list ?prop [] .
FILTER NOT EXISTS {
?list ?prop ?value .
FILTER NOT EXISTS {
?store ?prop ?value .
}
}
}
ORDER BY ?list ?store
However, this query returns all combinations of stores and lists, since every store charges 10.0f for parking. How can I filter only those stores, which meet all the requirements of a list? An additional assumption is, that there may exist other business models than buy and rent, as well as other criteria, i.e. data properties, which are of interest, too. This is why I do not want to specify these properties, but want to use variables instead.
This query did what I intended to do:
PREFIXES [as above]
PREFIX : <http://www.shopping.org/model#>
SELECT DISTINCT ?list ?store
WHERE {
?list a :ShoppingList .
?store a :Store .
FILTER NOT EXISTS {
?compat a owl:DatatypeProperty
FILTER NOT EXISTS {
?list ?compat ?value .
?store ?compat ?value .
}
}
FILTER NOT EXISTS {
?subset a owl:ObjectProperty .
?list ?subset ?value .
FILTER NOT EXISTS {
?store ?subset ?value .
}
}
}
ORDER BY ?list ?store
My mistake was actually just that I defined the ?prop outside of the filters. This resulted in them being part of the solution, i.e. I was was unable to remove whole stores through the filter(s).