graphdb owl-max cardinality restriction not working - owl

Can I restrict insert of data in graphdb based on cardinality rules defined in my ontology.
I loaded the following ontology in a graphdb repository with "owl-max" Ruleset. Based on discussion here. I am trying to restrict that a person can have only one "age" property.
#prefix : <http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
:Person a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
owl:cardinality "1"^^xsd:nonNegativeInteger ;
owl:onProperty :hasAge
] .
<http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age>
a owl:Ontology .
:hasAge a owl:DatatypeProperty .
I now insert a person record as below
prefix : <http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age#>
prefix data: <http://data.example.com/>
Insert DATA {
data:dow a :Person ;
:hasAge 26 .
}
The next time i insert an updated age for that person,
Insert DATA {
data:dow :hasAge 27 .
}
I expected an that age 27 triple overrides age 26 triple or I get an insert error. However both ages are stored for the person.
data:dow a <http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age#Person> ;
<http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age#hasAge> "26"^^xsd:integer , "27"^^xsd:integer .

disclaimer: This is not meant to be a proper nor correct answer, I just used it because formatting in comment is weird.
Not sure whether owl-max profile supports the inconsistency rule you'd need here. As a workaround, you could at least try to add a custom rule:
PREFIX sys: <http://www.ontotext.com/owlim/system#>
INSERT DATA {
<_:custom> sys:addRuleset
'''Prefices {
x : http://stackoverflow.com/q/24188632/1281433/people-have-exactly-one-age#
}
Axioms {}
Rules
{
Consistency: max_one_age_value
a <x:hasAge> b
a <x:hasAge> c [Constraint b != c]
-----------------------
}'''
}

Thanks to #aksw for the excellent answers. According to http://graphdb.ontotext.com/documentation/standard/reasoning.html#predefined-rulesets, owl-max and owl-rl should do what was asked.
I want to add a clarification: #trace-log, there is no implicit "overwrite " operation in SPARQL, and it doesn't matter what rule set you use. You must use the DELETE...INSERT... statement to update triples in the way you describe.

Related

SPARQL how to use concatenated strings for a subject of a subquery?

I created a SPARQL query like below. I get ?year and ?month from SERVICE query in Wikidata, and would like to use them as a part of a subject of a subquery (i.e. ?uri ?p ?o part). I managed to concatenate ?year and ?month and generate a URI, but somehow the the query does not return a result.
I tested both the subquery part (e.g. only using <https://example.com/date/10-1> ?p ?o) and the SERVICE query individually. They both return results properly (13 and 5 results respectively, so the size is not an issue). My guess is it is concatenated variable is a string not URI, which cannot be a subject. But I am not sure. As I am not sure what is wrong, I tried similar queries, but they get time-out, due to the subquery I think. Can you spot the problem and let me know how to fix it? Many thanks in advance!
SELECT DISTINCT ?event ?eventLabel ?d1 ?d2 ?d3 ?date ?year ?month ?uri ?p ?o
WHERE {
SERVICE <https://query.wikidata.org/sparql> {
select DISTINCT ?event ?eventLabel ?d1 ?d2 ?d3 ?date ?year ?month
where{
?event wdt:P31/wdt:P279* wd:Q13418847 .
?event wdt:P276 wd:Q1741 .
OPTIONAL {?event wdt:P580 ?d1}
OPTIONAL {?event wdt:P585 ?d2}
OPTIONAL {?event wdt:P582 ?d3}
BIND(IF(!BOUND(?d1),(IF(!BOUND(?d2),?d3,?d2)),?d1) as ?date)
BIND(year(?date) AS ?year)
BIND(month(?date) AS ?month)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE], en". }
}
ORDER BY ?date
LIMIT 100
}
BIND(CONCAT("<https://example.com/date/", str(?year), "-", str(?month), ">") AS ?uri) .
{
SELECT ?uri ?p ?o
WHERE {?uri ?p ?o .}
LIMIT 10
}
}
You can use the IRI function to make the string (without the </>) into a URI:
BIND(IRI(CONCAT("https://example.com/date/", str(?year), "-", str(?month))) AS ?uri) .

SPARQL DBPedia query for seating capacity, optimize and remove duplicates

I want to get all objects with seating capacity information on DBPedia. Optionally, I want to get their label, address, lat and lon information.
My issue is that I get a lot of duplicates even after filtering by language. How can I get distinct entries based on, say, 'address', or any other attribute?
Also, can you tell which part of this query can be improved so that my query doesn't time out when I use the public DBpedia endpoint? Thanks!
PREFIX dbpediaO: <http://dbpedia.org/ontology/>
SELECT ?place ?label ?capacity ?address ?lat ?lon WHERE {
?place dbpedia2:seatingCapacity ?capacity .
OPTIONAL{
?place dbpediaO:address ?address .
?place rdfs:label ?label .
?plage geo:lat ?lat .
?place geo:long ?lon .
}
filter (lang(?label) = "en" || lang(?label) = "eng")
filter (lang(?address) = "en" || lang(?address) = "eng")
}
Your places have multiple values of, for example, address. The unique thing is the URI itself. Moreover, you should put each property in a separate OPTIONAL, or at least use separate OPTIONAL clauses for lat/long. For label you do not need an OPTIONAL clause at all in DBpedia. The only way to get unique places is to group by the place and sample or group_concat all other properties. Something like this:
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?place (sample(?_label) as ?label)
(group_concat(?capacity; separator=";") as ?capacities)
(group_concat(?address; separator=";") as ?adresses) ?lat ?lon
WHERE {
?place dbo:seatingCapacity ?capacity ;
rdfs:label ?_label .
filter (langmatches(lang(?_label),"en"))
OPTIONAL {
?place dbo:address ?address .
filter (langmatches(lang(?address), "en"))
} OPTIONAL {
?place geo:lat ?lat ; geo:long ?lon .
}
}
group by ?place ?lat ?lon
order by desc(?place)
limit 100
As you can see, there are also multiple capacity values for places.

Parsing string in TurtleSyntax to OWLClass

Currently I am trying to create OWLClass from a string in Turtle syntax by first creating Jena OntModel and visiting each statement within the class. Is there a better way to create OWL Class using OWL API from Turtle syntax? Below is the string which I am trying to parse.
#prefix p0: <http://rdf.test.com/dl_reasoning/> .
#prefix p1: <http://rdf.test.com/ns/test_rm#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
p0:safetyGoal_1 a rdfs:Class , p1:SafetyGoal ;
rdfs:subClassOf p1:SafetyGoal ;
p1:fulfilledBy p0:fsr_fuel , p0:fsr_coo .
p0:safetyGoal_3 a rdfs:Class , p1:SafetyGoalVersion ;
rdfs:subClassOf p1:SafetyGoal ;
p0:safetyGoal_2 a rdfs:Class , p1:SafetyGoalVersion ;
rdfs:subClassOf p1:SafetyGoal ;
p1:fulfilledBy p0:fsr_fuel ;
p1:fulfills p0:fsr_coo .
The string you're trying to parse does not contain just classes - it contains axioms as well. In order to be a full ontology, it only lacks an ontology declaration. It should be possible to parse this straight to an ontology - which would be anonymous - by parsing it with one of the Turtle parsers in OWLAPI.
Have you tried parsing this to an OWLOntology?
String in = "...";
StringDocumentSource input = new StringDocumentSource(in);
OWLOntologyManager m = OWLManager.createOWLOntologyManager();
OWLOntology o = m.loadOntologtFromOntologyDocument(input);
Listing the axioms or iterating through the signature of the ontology should provide you with enough structure to move forward in your work.
Side note: these two lines seem to be missing a dot:
p0:safetyGoal_3 a rdfs:Class , p1:SafetyGoalVersion ;
rdfs:subClassOf p1:SafetyGoal ;
There should be a full stop to allow parsing:
p0:safetyGoal_3 a rdfs:Class , p1:SafetyGoalVersion ;
rdfs:subClassOf p1:SafetyGoal .

SPARQL union not merging the results

I have a sparql query which is the union of three individual queries. On the union i apply a filter. Although my individual queries return rows, but the union doesn't return any rows. I have checked that the output of individual queries have rows which satisfy the outer filter criteria.
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX yago: <http://dbpedia.org/class/yago/>
SELECT *
where{
{
SELECT (?LandingURI) AS ?URI ?category
WHERE {
{
?LandingURI rdfs:label ?term .
?LandingURI (dcterms:subject|rdf:type) ?category .
}
FILTER((?term ="Roger"#en))
}
}
UNION
{
SELECT (?redirects) AS ?URI ?category
WHERE {
{
?LandingURI rdfs:label ?term .
?LandingURI <http://dbpedia.org/ontology/wikiPageRedirects> ?redirects .
?redirects (dcterms:subject|rdf:type) ?category .
}
FILTER((?term ="Roger"#en))
}
}
UNION
{
SELECT (?disambiguates) AS ?URI ?category
WHERE {
{
?LandingURI rdfs:label ?term .
?LandingURI <http://dbpedia.org/ontology/wikiPageDisambiguates> ?disambiguates .
?disambiguates (dcterms:subject|rdf:type) ?category .
}
FILTER((?term ="Roger"#en))
}
}
FILTER (?category = dbpedia-owl:TennisPlayer ||
?category = yago:TennisOrganisations ||
?category = <http://dbpedia.org/resource/Category:The_Championships,_Wimbledon>
)
}
I don't know what software you're using to process your query, but it shouldn't accept that query at all; it's not well-formed. You can check your query at sparql.org's query validator.
The bracketing in your query makes it hard to tell exactly where the union is placed, but just in case it's not , union should appear between two group graph patterns, e.g.: { ... } UNION { ... }.
All that said, there's actually no need to use union (or filter) here at all. You can do this all with property paths and values. If I understand it correctly, your query can be rewritten as:
select ?uri ?term ?category where {
#-- acceptable values of ?category
values ?category {
dbpedia-owl:TennisPlayer
yago:TennisOrganisations
<http://dbpedia.org/resource/Category:The_Championships,_Wimbledon>
}
#-- acceptable values of ?term
values ?term {
"Roger"#en
}
#-- get the rdfs:label of the ?landingUri, then
#-- follow an optional redirect or disambiguation
#-- link to the actual uri, and then get any
#-- dcterms:subject or rdf:type from the actual uri.
?landingUri rdfs:label ?term .
?landingUri (dbpedia-owl:wikiPageRedirects|dbpedia-owl:wikiPageDisambiguates)? ?uri
?uri (dcterms:subject|rdf:type) ?category .
}

SPARQL: union on dbpedia changes birthdate

I'm facing a strange behavior by using "union" on the endpoint http://de.dbpedia.org/sparql.
By using
SELECT distinct *
WHERE {
{
?name dcterms:subject category-de:Haus_Liechtenstein.
?name rdf:type foaf:Person.
?name <http://dbpedia.org/ontology/birthDate> ?birthdate.
Optional {?name dbpedia-owl:deathDate ?deathDate.}
Optional {?name <http://de.dbpedia.org/property/gnd> ?gnd.}
}
filter (!bound(?deathDate))
}
Order BY ASC (?birthdate)
the birthdate of "Marie Kinsky" for example is "1940-04-14Z", which is correct (1st row). When I'm now adding a second source with union:
SELECT distinct *
WHERE {
{
?name dcterms:subject category-de:Haus_Liechtenstein.
?name rdf:type foaf:Person.
?name <http://dbpedia.org/ontology/birthDate> ?birthdate.
Optional {?name dbpedia-owl:deathDate ?deathDate.}
Optional {?name <http://de.dbpedia.org/property/gnd> ?gnd.}
}
union{
SERVICE silent <http://dbpedia.org/sparql>{
?name dcterms:subject category-en:Princely_Family_of_Liechtenstein.
?name rdf:type foaf:Person.
?name dbpprop:father ?father.
?name dbpprop:mother ?mother.
?name dbpprop:birthDate ?birthdate.
Optional{?name dbpedia-owl:spouse ?spouse.}
Optional{?name dbpprop:shortDescription ?title.}
Optional{?name dbpedia-owl:individualisedGnd ?gnd.}
Optional {?name dbpedia-owl:deathDate ?deathDate.}
}}
filter (!bound(?deathDate))
}
Order BY ASC (?birthdate)
then I get the Birthdate of "Marie" with "1940-04-13+02:00" which is wrong (first row). By checking the date manually Marie, the birthdate is "1940-04-14".
Can someone explain me this behavior?
Thank you in advance and best regards
Fobi
Try the following query (a very cut down version of your original) on http://de.dbpedia.org/sparql:
PREFIX category-en: <http://dbpedia.org/resource/Category:>
SELECT distinct *
WHERE {
SERVICE silent <http://dbpedia.org/sparql> {
?name dcterms:subject category-en:Princely_Family_of_Liechtenstein.
?name dbpprop:birthDate ?birthdate.
}
}
Note that each of the dates have this suspicious timezone shift, and Marie has 1940-04-13+02:00.
Now try the following on http://dbpedia.org/sparql:
PREFIX category-en: <http://dbpedia.org/resource/Category:>
SELECT distinct *
WHERE {
?name dcterms:subject category-en:Princely_Family_of_Liechtenstein.
?name dbpprop:birthDate ?birthdate.
}
Now I see Marie has birth date 1940-04-14+02:00!
I wonder whether the dbpedia endpoint is trying to make time zone corrections based on the locale of the client? But it really isn't getting it right.
(It's not just Liechtenstein royalty, most birth dates have this feature)
Update:
From the dbpedia mailing list:
We recently recognized that there are inconsistencies with dates in the DBpedia
Sparql endpoint:
dates in the SPARQL endpoint are timezoned +02:00 while on the DBpedia pages
and in the dumps they are not.
[...]
That is most probably an issue of Virtuoso and there already was an issue
raised in 2011 on the virtuoso-users mailing list

Resources