skos broader and narrow inverse not working - graphdb

I have setup GraphDB SE trial version and trying out inference functionality with OWL2-RL ruleset. I have built a simple SKOS knowledge with a single broader relationship. Some how, when I try to query for narrower relationship am not getting any results. Am I going wrong in the usage ?
Insertion:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
INSERT DATA {
ex:mammals rdf:type skos:Concept;
skos:prefLabel "mammals"#en;
ex:animals rdf:type skos:Concept;
skos:prefLabel "animals"#en;
skos:broader ex:mammals .
}
Query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
select * where {
?s skos:narrower ?o .
}
In the query result I don't see any response. Shouldn't it return below result -
ex:mammals skos:narrower ex:animals

I just came across this question and the OP is correct: Although the official SKOS reference explicitly states that skos:broader and skos:narrower are inverse, the actual RDF implementation does not include this statement. However, properties skos:broaderTransitive and skos:narrowerTransitive are declared as inverse.
And, although not relevant to the original question, the implementation does not state properties skos:topConceptOf and skos:hasTopConcept as inverse either.

Related

Construct loop in SPARQL

The following SPARQL query
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix msc: <http://msc.org/resources/MSC/msc2020/>
construct {?s skos:broader msc:00-XX . }
where
{
?s a skos:Concept ; skos:notation ?notation.
filter regex (?notation, "00-\d\d")
}
searches all notations 00-01, 00-02, etc. and constructs a relation to the top level class 00-XX. However, this is only the first of 63 top level classes altogether, so I would like to "loop" over all top level classes automatically. On top, I would like to adapt this to other patterns. Is there a way to do this with SPARQL? If not, what would you recommend instead?
In the meantime we found a solution without SPARQL.
The SPARQL CONSTRUCT query was supposed to create a skos:broader relation between a skos:Concept with a notation like "00-01" (and all other concepts with 00-\d\d notation) and its proper subordinate concept, which for 00-01 is the skos:Concept with the notation 00-XX.
The data originate from a table and Open Refine is much faster in creating the skos:broader statements than using the SPARQL query proposed above and adjusting it to other notation patterns.
We use GREL's value.replace on the cells with the notations to create a new column:
value.replace(/-\d\d/, "-XX").replace(/\d\d>/, "xx>")
The two replacements give us the notation of the original notation's superordinate concept in one step. The second replace already adapts to the other patterns mentioned in the question (e.g. 00A01).
With the original notation and the value in the new column, we can easily create the skos:broader triples by concatenating text and the values from both columns. These can then be exported from OpenRefine and just be copy-pasted to our SKOS vocabulary.
Here is a SPARQL answer based on the query in the question. Using filters and regex (as suggested in the comment by Yahalnaut as a reply to UninforomedUser above) is needed. Creating a skos:broader relation based on two concept's notations requires them to hava an identical sequence of digits before the - . The comparison should only between the first part of the notations, so each 00- should match another 00-but not a 01-. As asked, the solution below only considers topConcepts of the Vocabulary as potential objects for skos:broader. The concepts should also not relate to themselves, therefore the last filter. This should then be adoptable to other patterns as well. Depending on the number of Concepts and the memory available for the query, this may last a while or even stop before finished. It eliminates lot of the effort though.
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix msc: <http://msc.org/resources/MSC/msc2020/>
construct {?s skos:broader ?y . }
where {
?s a skos:Concept ; skos:notation ?notation.
?y skos:topConceptOf msc: ; skos:notation ?not2.
bind (REPLACE (?not2 , "-XX" , "") as ?1)
bind (REPLACE (?notation , "-\d\d", "" ) as ?2 )
filter (?1 = ?2)
filter (?not2 != ?notation)
}

Can I constrain the owl:onProperties when traversing over owl:Restrictions?

I'd like to use ChEBI to determine which molecular entities could be considered "taxanes", in the informal language that physicians use.
The Anatomical and Therapeutic Classification places both docetaxel and paclitaxel in class L01CD "Taxanes", but in ChEBI the paths include both subclass relations and
'has parent hydride' some 'taxane' relations, from an OWL perspective. The following SPARQL finds both docetaxel and paclitaxel
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
select * where {
?drug (rdfs:subClassOf|owl:someValuesFrom)*
<http://purl.obolibrary.org/obo/CHEBI_36064> .
optional {
?drug rdfs:label ?l .
}
}
order by ?l
I'm not explicitly requiring here that the owl:someValuesFrom predicate is applied to an owl:Restiction in the rdfs:subClassOf path. How could I limit this query so that only certain owl:onPropertys (like 'has parent hydride') are allowed in combination with that implicit owl:Restriction?
I'm afraid that this query is dangerously under specified as it is.

DBPedia-France (fr.dpbedia.org/sparql) query giving different result from a call to another

I'm calling on http://fr.dbpedia.org/sparql
the following SPARQL query:
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select distinct ?lcs where {
{
?lcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class .
filter not exists {
?llcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class ;
rdfs:subClassOf+ ?lcs .
}
}
}
On some call I've http://dbpedia.org/ontology/Person as result, on others call I'm getting http://dbpedia.org/ontology/Person and http://dbpedia.org/ontology/Agent and with others the previous answers plus http://www.w3.org/2002/07/owl#Thing
without nothing to know that a response isn't complete. How can I use the result, if it is a little randomized
The main reason for your query not working as expected is that the data the data is i) split into separate graphs and ii) not all graphs were added to the default graph.
To keep it short, the instance data is contained inside the graph http://fr.dbpedia.org whereas the schema triples will be accessible via http://dbpedia.org graph only. Sometimes, if no graph is given, then the union of some graphs is used as the default graph which will be the dataset at query time. Unfortunately, this doesn't hold for the French DBpedia endpoint, only the instance data graph will be used.
You can check this with
DESCRIBE <http://dbpedia.org/ontology/Person>
which is empty when using either no graph explicitly or the graph http://fr.dbpedia.org, but non-empty for graph http://dbpedia.org.
The way to define the default graph is using the keyword FROM. For your query, it should therefore be
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select distinct ?lcs
from <http://fr.dbpedia.org>
from <http://dbpedia.org>
where {
?lcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class .
filter not exists {
?llcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class ;
rdfs:subClassOf+ ?lcs .
}
}
Note, while this seems to return the correct result, you should also consider the comment from #TallTed regarding possible differences among language chapters (e.g. English vs French Wikipedia as source), release dumps (2016 vs 2018 or even the DBpedia Live) as well as Virtuoso versions used as backend.

SPARQL - Inverse Path of dynamic discovered relationship

I have a Graph Database that implements only one side of relationships in the model structures. For instance, All Broader relationships are mapped as skos:broader. All Narrower relationships are mapped as ^skos:broader (for whatever reasons they chose to do this, I have no control over this.)
I am trying to write a SPARQL Query that delivers something like
Query for all relationships of a given IRI, and their associated values.
The goal is to make a JSON or XML Representation of all the content.
Here is what I have working.
PREFIX skosxl: <http://www.w3.org/2008/05/skos-xl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?relation ?value
where
{
<CONCEPT_URI> ?r ?c
OPTIONAL {
?r rdfs:label|skosxl:prefLabel ?l
}
OPTIONAL {
?c skosxl:prefLabel/skosxl:literalForm|skosxl:literalForm ?d .
}
BIND ( if (bound(?d), ?d, ?c) as ?value )
BIND ( if (bound(?l), ?l, strafter(?r, '#')) as ?relation )
}
This works to give me all the concept relationships (IE: Broader), but it does not give me the narrower items (IE: ^broader).
Is there anyway that I can extend this generic query to produce the inverses of any relationships it finds, as well? I Tried simply adding the ^ to the ?r in the where clause but it does not like that syntactically.
Thanks,

Querying polymorphism in RDF database using SPARQL

I have a question about polymorphism in RDF schema.
I created a class "MobilePhone":
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix schema: <http://schema.org/> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix my: <http://localhost/> .
my:MobilePhone rdf:type rdfs:Class .
my:MobilePhone rdfs:subClassOf schema:Product .
my:MobilePhone rdfs:label "MobilePhone" .
Then I executed two queries:
PREFIX : <http://schema.org/>
PREFIX my: <http://localhost/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?instance
WHERE {
?instance a my:MobilePhone .
}
and
PREFIX : <http://schema.org/>
PREFIX my: <http://localhost/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?instance
WHERE {
?instance a :Product .
}
I expected the second query to retrieve all Products. Even "MobilePhone" products. But that didn't happen. I had to use:
PREFIX : <http://schema.org/>
PREFIX my: <http://localhost/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?instance
WHERE {
?class rdfs:subClassOf* :Product .
?instance rdf:type ?class .
}
Does anyone know if it is possible to update my schema so the first query for searching all Products would work?
It is possible to update your data (not your schema [or ontology]) to deliver the desired result, by "forward chaining" -- i.e., by explicitly including statements that each entity which is a my:MobilePhone is also a :Product.
It's also possible to use "backward chaining" to deliver the desired result; the specifics of this will vary with your triple/quad store and other software. (My employer's solution, Virtuoso, uses a DEFINE input:inference pragma to activate an inference rule set for each query.)
Both of these may be considered as "inferencing" or "reasoning", though common usage generally applies these terms only to the dynamic action -- which happens with every query in "backward chaining", and once, pre-query, typically during data load, in "forward chaining".