SWRL rules in protege 3.4.8 - owl

I created an ontology that contains the class Blood_Sugar
this class contains 4 subclasses: Normal_BS, High_BS, Low_BS and Dangerous_BS.
I would like to execute a SWRL rule on Protege 3.4.8 which permit to classify individuals of the supere class Blood_Sugar in subclasses according to their values.
Blood_Pressure(?x) ∧ hasLevelvalue(?x, ?y) ∧ swrlb:greaterThan(?y, 126) ∧ swrlb:lessThan(?y, 500) → High_BS(?x)
knowing that hasLevelValue is a DataType proprety, its domain is Blood_Sugar class and its range is INT
On the Blood_Sugar class and thier subclasses class, I created the restriction (hasLevelvalue only int)
I created som individuals that have diffrent values but they are not classified in the sub classes (High_BS, Low_BS...) the swrl rule does not give an erreur but it does not give a result :( I dont know what end wher is the problem?!!!!!

Possible problems
Your question is a bit unclear, and I'm not sure whether there are just typographical errors, or if there are genuine modeling errors. You said that you were looking at the class Blood_Sugar, and four subclasses, but then the rule that you showed starts with a Blood_Pressure atom (pressure, not sugar), and that could be the problem right there:
Blood_Pressure(?x) ∧ hasLevelvalue(?x, ?y) ∧ swrlb:greaterThan(?y, 126) ∧ swrlb:lessThan(?y, 500) → High_BS(?x)
If that's just a typo in the question, though, you could be having problems with the datatypes. Rather than using xsd:int, you should probably be using xsd:integer (so that you don't have to worry about issues with overflow, etc.) Not to mention, if you use one in your data, but declare the range differently, you could run into inconsistencies there.
Using Rules
To get you going, I've reconstructed a very minimal part of your ontology in Protégé 4.x, and using the Pellet reasoner, I've demonstrated the results that you're looking for:
I've included the ontology in N3 format toward the end of this answer.
Using Restrictions
Now, even though you can do this using SWRL rules, you can also do this using simple OWL restriction classes, and that might be a better option, because it might work with more reasoners. If nothing else, it's one less dependency, so it might be a more attractive solution. The trick is to either define Blood_HS as equivalent to the intersection of Blood_Sugar and things with a level in the desired range, or you could use an general class axiom. In both of these cases, you can get the desired result using the Pellet reasoner, and you don't need any SWRL rule.
Using an Equivalent Class Axiom
You can simply say that (using the class names that I've been using in mine ontology):
HighBloodSugar ≡ BloodSugar and (hasLevelValue some integer[>120,<600])
In Protégé that looks a little bit different, but it's pretty close:
Using a Subclass Axiom
Now, if you you don't want to make that an equivalent class axiom, you can use a general axiom like the following.
BloodSugar and (hasLevelValue some integer[>120,<600]) &sqsubseteq; HighBloodSugar
This only looks a little bit different in Protégé. This is the closest to the SWRL version, since anything that is a blood sugar and has a level in the specified range will be classified as a high blood sugar, but it's still possible that there are other high blood sugars, too. (You don't get this with the equivalent class axiom.)
Ontology with Rules
#prefix : <http://stackoverflow.com/q/21243879/1281433/blood-pressure.owl#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix swrl: <http://www.w3.org/2003/11/swrl#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix swrlb: <http://www.w3.org/2003/11/swrlb#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix blood-pressure: <http://stackoverflow.com/q/21243879/1281433/blood-pressure.owl#> .
<http://stackoverflow.com/q/21243879/1281433/blood-pressure.owl>
a owl:Ontology .
blood-pressure:HighBloodSugar
a owl:Class .
blood-pressure:bs1 a owl:NamedIndividual , blood-pressure:BloodSugar ;
blood-pressure:hasLevelValue 200 .
<urn:swrl#bp> a swrl:Variable .
<urn:swrl#bs> a swrl:Variable .
blood-pressure:BloodSugar
a owl:Class .
blood-pressure:hasLevelValue
a owl:DatatypeProperty ;
rdfs:domain blood-pressure:BloodSugar ;
rdfs:range xsd:integer .
[ a swrl:Imp ;
swrl:body [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#bs> ;
swrl:classPredicate blood-pressure:BloodSugar
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:DatavaluedPropertyAtom ;
swrl:argument1 <urn:swrl#bp> ;
swrl:argument2 <urn:swrl#level> ;
swrl:propertyPredicate blood-pressure:hasLevelValue
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:BuiltinAtom ;
swrl:arguments [ a rdf:List ;
rdf:first <urn:swrl#level> ;
rdf:rest [ a rdf:List ;
rdf:first 126 ;
rdf:rest ()
]
] ;
swrl:builtin swrlb:greaterThan
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:BuiltinAtom ;
swrl:arguments [ a rdf:List ;
rdf:first <urn:swrl#level> ;
rdf:rest [ a rdf:List ;
rdf:first 500 ;
rdf:rest ()
]
] ;
swrl:builtin swrlb:lessThan
] ;
rdf:rest ()
]
]
]
] ;
swrl:head [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#bs> ;
swrl:classPredicate blood-pressure:HighBloodSugar
] ;
rdf:rest ()
]
] .
<urn:swrl#level> a swrl:Variable .

Related

OWL - associate transitive child with great-parent

I would like to simplify my SHACL definitions by reversing the relations between shapes, properties and groups.
A typical NodeShape looks like this. Two properties in a group:
<>
a sh:NodeShape ;
sh:property
[
sh:name "Property 1" ;
sh:order 1 ;
sh:group <#Group> ;
] ,
[
sh:name "Property 2" ;
sh:order 2 ;
sh:group <#Group> ;
] ;
.
It becomes a little unwieldy when there are multiple groups and many properties because all of them are tangled in the sh:property list of objects.
What I would like to achieve is to revers the relations a little using OWL rules so that I could type the RDF differently, but retain the equivalence with the above using reasoning.
<>
a sh:NodeShape ;
ex:group <#Group> ;
.
<#Property1>
sh:name "Property 1" ;
sh:order 1 ;
.
<#Property2>
sh:name "Property 2" ;
sh:order 2 ;
.
<#Group>
ex:property <#Property1>, <#Property2>
.
Is there a way to define ex:group and ex:property to infer the triples from first snippet?

Jena Model Validation OntModel

I have created an Ontology which i want use for validating instances, following is the test setup i have, couldnt get validation report one of uid is zero. which is xsd:minExclusive "0"^^xsd:unsignedLong.
Can anyone help m eunderstand best practice to use Jena, i am inteding to sue default model to recieve an input validating aginast ontModel and the merging in TDB backed model.
:Book rdf:type owl:Class ;
rdfs:subClassOf Model .
and data Property
:uid rdf:type owl:DatatypeProperty ,
owl:FunctionalProperty ;
rdfs:domain :Model ;
rdfs:range [ rdf:type rdfs:Datatype ;
owl:onDatatype xsd:unsignedLong ;
owl:withRestrictions ( [ xsd:minExclusive "0"^^xsd:unsignedLong
]
)
] .
Trying to use this ontology to validate data
OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RDFS_INF);
ontModel.read(getClass().getClassLoader().getResource("model.owl").toExternalForm(), NS);
// ontModel.write(System.out);
Reasoner reasoner = ontModel.getReasoner().bindSchema(ontModel);
Model data = createTestData();
//data.write(System.out);
InfModel infModel = ModelFactory.createInfModel(reasoner, data);
ValidityReport report = infModel.validate();
if (report.isValid())
System.out.println("valid");
and in the following code //(index - 1) ensure at least one id of 0
public static Model createTestData() {
Model instances = ModelFactory.createDefaultModel();
instances.setNsPrefix("rdfs", RDFS.getURI());
instances.setNsPrefix("rdf", RDF.getURI());
instances.setNsPrefix("a", NS);
instances.setNsPrefix("", NS + "#");
Property UID_PROPERTY = ResourceFactory.createProperty(NS + "#uid");
IntStream.of(1, 2, 3).forEach(index -> {
Resource r = instances.createResource(NS + "/item/" + (index - 1));
r.addProperty(UID_PROPERTY, ResourceFactory.createTypedLiteral((index - 1)));
});
return instances;
}

SPARQL, dbpedia : Retrieve values of resource linked as property, type person

I need to retrieve the name of a person's mother, and I have no idea how to do so.
This is the query I'm currently working with:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX : <http://dbpedia.org/resource/>
SELECT DISTINCT
?resource ?depiction ?label ?parent ?bd
WHERE {
?resource a dbo:Royalty ; foaf:depiction ?depiction ; rdfs:label ?label;
dbo:parent ?parent; dbo:birthDate ?bd;
dbo:birthPlace ?bp . ?bp dbo:isPartOf :England .
FILTER(
LANGMATCHES(LANG(?label), 'en') && ?bd < '1900-01-01'^^xsd:date)
}
ORDER BY DESC(?bd)
Some of it was given, some of it was added by me.
As you can see I want to retrieve all royals (with Label and depiction) who were born in England before 1900. But I also want to retrieve the name of a person's mother.
?parent contains links to the person's parents and I can't seem to figure out how to:
retrieve only the mother and
How to get her name/label, since this only returns the url.
For example:
For: http://dbpedia.org/page/Charlotte_of_Mecklenburg-Strelitz
?parents are:
http://dbpedia.org/page/Princess_Elisabeth_Albertine_of_Saxe-Hildburghausen
and
http://dbpedia.org/page/Duke_Charles_Louis_Frederick_of_Mecklenburg
But I would need :
Princess Elisabeth Albertine of Saxe-Hildburghausen
As commented by #AKSW, a possibly-incomplete query (formatted here for improved clarity) --
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX yago: <http://dbpedia.org/class/yago/>
PREFIX : <http://dbpedia.org/resource/>
SELECT DISTINCT
?resource
?label
?bd
?depiction
?parent
?parentLabel
WHERE
{ ?resource a dbo:Royalty ;
foaf:depiction ?depiction ;
rdfs:label ?label ;
dbo:parent ?parent ;
dbo:birthDate ?bd ;
dbo:birthPlace/dbo:location?/dbo:isPartOf :England .
?parent rdfs:label ?parentLabel .
FILTER ( LANGMATCHES ( LANG ( ?parentLabel ), 'en' )
&& LANGMATCHES ( LANG ( ?label ), 'en' )
&& ?bd < '1900-01-01'^^xsd:date
)
{ ?parent foaf:gender "female"#en }
UNION
{ ?parent a yago:Female109619168 }
}
ORDER BY DESC(?bd)

OWL: how to limit the range of a value

For example, I need to describe a dog between age 1 and 4. How do I restrict the value range of a property? There are minCardinality and maxCardinality for number of property. But not suitable for my example.
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="4"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
As an concrete example, how to translate above xsd to owl?
You can define a qualified cardinality restriction directly as a local class restriction. For example, to define that an amoeba has an age range of 1 to 4, use the following:
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/things#age"/>
<owl:maxQualifiedCardinality rdf:datatype="xs:nonNegativeInteger">4</owl:maxQualifiedCardinality>
<owl:onDataRange rdf:resource="http://example.org/things#Amoeba"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/things#age"/>
<owl:minQualifiedCardinality rdf:datatype="xs:nonNegativeInteger">1</owl:minQualifiedCardinality>
<owl:onDataRange rdf:resource="http://example.org/things#Amoeba"/>
</owl:Restriction>
</rdfs:subClassOf>
That's a bit difficult to read. The equivalent Turtle serialization is considerably easier to read and manage (note the direct representation of triples. JSON-LD is another readily consumable text serialization for RDF):
rdfs:subClassOf [
rdf:type owl:Restriction ;
owl:maxQualifiedCardinality "4"^^xs:nonNegativeInteger ;
owl:onDataRange ex:Amoeba ;
owl:onProperty ex:age ;
] ;
rdfs:subClassOf [
rdf:type owl:Restriction ;
owl:minQualifiedCardinality "1"^^xs:nonNegativeInteger ;
owl:onDataRange ex:Amoeba ;
owl:onProperty ex:age ;
] ;

Jena TDB/Fuseki indexing for text search: Customize the URI location for each field

I have triple store of a relatively small size, which I store and access via Jena Fuseki. Here is a snippet of my data, though more optional fields can occur:
<http://example.com/#org1>
a pers:family ;
pers:name [ pers:lang "de" ;
pers:occurence "XX" ;
pers:surname "NN" ;
pers:type "std" ;
pers:var_id <http://example.com/#org1.01>
] ;
pers:org_type "Family" .
<http://example.com/#per1>
a pers:person ;
pers:first_mentions [ pers:first_mention "1234" ;
pers:occurence "XX"
] ;
pers:name [ pers:forename "Maria" ;
pers:id <http://example.com/#per1a> ;
pers:lang "de" ;
pers:occurence "XX" ;
pers:org_id <http://example.com/#org1> ;
pers:type "std"
] ;
pers:name [ pers:forename "Marie" ;
pers:lang "fr" ;
pers:occurence "XX" ;
pers:org_var_id <http://example.com/#org1.01> ;
pers:type "orig" ;
pers:var_id <http://example.com/#per1a.01>
] ;
pers:org_id <http://example.com/#org1> ;
pers:sex "1" .
Planning to implement faceted search, I have just indexed my triple store.
It was indexed OK and I have access to the index via Solr.
I configured my the indexing in my config.ttl based on the few examples found around the web.
Here is the part of my config that I have questions about:
<#entMap> a text:EntityMap ;
text:entityField "uri" ;
text:defaultField "text" ;
text:map (
[ text:field "text" ; text:predicate rdfs:label ]
[text:field "forename" ; text:predicate pers:forename ]
[text:field "surname" ; text:predicate pers:surname ]
[text:field "orgtype" ; text:predicate pers:org_type ]
[text:field "occur" ; text:predicate pers:occurence ]
[text:field "lang" ; text:predicate pers:lang ]
[text:field "description" ; text:predicate pers:description ]
[text:field "sex" ; text:predicate pers:sex ]
[text:field "marital" ; text:predicate pers:marital_status ]
[text:field "role" ; text:predicate pers:rolename ]
) .
When I query the Solr, sending this query:
http://localhost:8983/solr/project/select?q=*Mari*&wt=json&indent=true
it outputs smth like this:
{
"responseHeader":{
"status":0,
"QTime":16,
"params":{
"q":"*Mari*",
"indent":"true",
"wt":"json"}},
"response":{"numFound":39,"start":0,"docs":[
{
"uri":["_:6fdab61c39c226f305e6419d6aa5f5e9"],
"forename":["Maria"],
"id":"c3f82e8c-9650-4a18-b6c3-1eaebff9830c",
"_version_":1515091600962748416} }}
A blank node is referenced as URI. So, I understood that according to my config file, the data was indexed in such a way that "text:entityField "uri"" would look for the subject of the "text:predicate". When I was querying the index for "Mari" and the occurence was found in the field "forename", it's subject was a blank node. But for a future work with index, i.e. for facets, I need the URI of the entity (e.g. http://example.com/#per1), because I cannot use the blank nodes IDs for querying, so I cannot find out to which entry they refer.
How can I index my data, so that I could tell Solr differently for each field, where is it's URI? For example, if the indexed field is "forename", it's URI would be found somehow like this:
[text:field "forename" ; text:predicate pers:forename ; text:entityField <pattern for finding URI of the forename field>]
<pattern for finding URI of the forename field>
URI pers:name [text:field "forename"]

Resources