Jena Custom Rules using Built-ins - jena

I am currently messing around with Jena trying to create rules to add to my generic reasoner. I created the following simple rule:
[rule1: (?x ?rdf:type ?y),(?y rdfs:subClassOf ?z)-> (?x rdfs:type ?z)]
This works fine, and fires correctly, giving me everything I expect. After I did this I wanted to assign a timestamp to ?x, so that I'd know when the conclusion was come to, I wanted to used the Now builtin as follows.
[rule1: (?x ?rdf:type ?y),(?y rdfs:subClassOf ?z),now(?x)-> (?x rdfs:type ?z)]
This unfortunately does not work, it does nor throw an error, it just does not seem to bind any time value to ?x and also it seems to prevent the rule from being fired correctly as in the first case. The ontology I am using is below. Any ideas?
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#">
<owl:Class rdf:about="livingthing"></owl:Class>
<owl:Class rdf:about="Human">
<rdfs:subClassOf rdf:resource="livingthing"/>
</owl:Class>
<rdf:Description rdf:about="john">
<rdf:type rdf:resource="Human"/>
</rdf:Description>
</rdf:RDF>

According to the javadoc, Now will “Bind the first arg to the current date time in the current locale and timezone.” I haven't tried using Now, but I'd expect that "the current date time in the current locale and timezone" is a some sort of RDF literal (perhaps a date or datetime)? Literals cannot be the subjects of triples in RDF. For the rule
[rule1: (?x ?rdf:type ?y),(?y rdfs:subClassOf ?z),now(?x) -> (?x rdfs:type ?z)]
to match in the graph, the variable ?x will be bound to the date literal, say, "2013-05-24" (but as I mentioned, I don't know exactly what Now will produce) but there cannot be any matches for (?x rdf:type ?y) because these would have the form "2013-05-24" rdf:type ?y and there cannot be triples of that form. This means that the rule cannot fire.
If you want to add a timestamp to something, you probably want an n-ary relation, so that you're actually representing (or representing, in addition to ?x rdf:type ?z) a relation inferredSubclassRule(?super,?sub,?time ), which can be represented in RDF by a blank node like:
[] a :inferredSubclassRule ;
:hasSuperClass ?super ;
:hasSubClass ?sub ;
:hasTimestamp ?time .

Related

Jena Fuseki missed inference?

I'm using Jena Fuseki 3.13.1 (with OWLFBRuleReasoner), and I have asserted (uploaded) the following triples:
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix f: <http://vleo.net/family#> .
f:Bob f:hasWife f:Alice .
f:Bob f:hasWife f:Alice2 .
f:Alice2 f:hasHusband f:Bob2 .
f:hasWife a owl:FunctionalProperty .
f:hasWife a owl:InverseFunctionalProperty .
f:hasHusband owl:inverseOf f:hasWife .
Now, If I query and ASK { f:Alice owl:sameAs f:Alice2 }, I get true.
However, If I ASK { f:Bob owl:sameAs f:Bob2 }, I get false! Loading the same triples on another reasoner (owl-rl), I get the triple f:Bob owl:sameAs f:Bob2 inferred.
What is happening here?
I have worked with jena reasoner following this doc:
https://jena.apache.org/documentation/inference/
I have many years of experience with jena, and had never used OWLFBRuleReasoner, and it does not appear in the indicated doc, which is curious for me.
Not all reasoners work with the same construct, and that is the reason why I check the doc, that means perhaps OWLFBRuleReasoner does not use the same owl construct as the another reasoner you used (owl-rl).
Another thing is that, as I understand your KB is inconsistent, because you are declaring:
f:hasWife a owl:FunctionalProperty
But, you are assigning 2 values to it, which must make your KB inconsistent.
Luis Ramos
A follow-up: as suggested by UninformedUser, I've asked this one on the Jena mailing list and got an answer from Dave.
Jena's implementation trades some reasoning completeness for performance, the solution in this case is to add explicitly the forward version of inverseOf to the owl-fb rules file:
[inverseOf2b: (?P owl:inverseOf ?Q), (?X ?P ?Y) -> (?Y ?Q ?X) ]
The details are in this thread.

Jena list statements with print builtin rule

I am trying to learn how Jena and GenericRuleReasoner works. I took this from Apache Jena tutorial.
[transitiveRule: (?A demo:p ?B), (?B demo:p ?C) -> (?A > demo:p ?C) ]
[symmetricRule: (?Y demo:p ?X) -> (?X demo:p ?Y) ]
If I want to add another statement
[testPrintRule: (?X demo:p ?Y) -> print(?Y, "for testing")] //Print only this
Is it possible for me to only list statement in print command? The print statement is printed in console. I want to display in my UI.
This is what I am currently doing in Jena to get the triples. I am sorry if I am wrong, I am a beginner.
Property p = ReadOntology.model.getProperty(ns + "demo:p");
List rules = Rule.rulesFromURL(FileLocations.getRulesLoc());
Reasoner reasoner = new GenericRuleReasoner( rules );
InfModel infModel = ModelFactory.createInfModel( reasoner, ReadOntology.model);
StmtIterator train = infModel.listStatements(null, p, (RDFNode)null);
Ok, if I understand you correctly you have 2 questions:
(1) you want to know whether you can use rules to print your triples, and
(2) you want to know whether you can write stuff from a Jena rule to you GUI.
Answer (1)
You can print your triple via a rule like
[rulePrintTriples: (?s ?p ?o) -> print(?s, ?p, ?o)]
though I do not think you should do that because it is likely to be very inefficient. Besides, Jena already has a way to do this easily, i.e.:
RDFDataMgr.write(System.out, model, RDFFormat.TTL);
Answer (2)
Yes, you could have a rule to write to your GUI, but for that you will have to create your own builtin type as explained here. Assuming for your GUI you are using some sort of MVC pattern you can update the model of your GUI when the rule is triggered with your custom rule code.
Again it may be questionable whether you want to do that since it may be brittle in the case where you GUI has not been initialized yet. A more robust approach would to add the triples to the Jena model and later, say when your GUI is initialized, run a SPARQL query against the Jena model and populate your GUI in that way.
I have written about Jena rules here and here.

OWL Ontology Predicate Logic with Jena

I'm having trouble expressing the following situation in my Ontology:
Suppose I have four people voting and four votes (so there is a one-to-one mapping between vote and voter). People can either vote yes or no. If I know the outcome of three people's votes, I ought to be able to deduce the fourth person's vote.
So to reiterate: John, Bob, Mary, and Carol each vote. Since there are four people there are four votes. The outcome of the vote is a tie (2 yes, and 2 no). Later on the reasoner determines that Bob and John voted no. The reasoner should then be able to deduce that Mary and Carol voted yes.
Currently I am building my ontology using Jena's java api and am inferencing with a Jena reasoner, so I'd rather use rules/semantics supported by Jena.
Antoine Zimmerman's answer is right in that this kind of thing is expressible in OWL, but that it requires a bit more work than you might expect, because you're trying to enforce a type of closed world reasoning and default reasoning, whereas OWL makes the open world assumption in which if you don't know something, it's not presumed to be either true or false, just unknown. Once the closure axioms are in place though, this isn't too hard of a scenario to write. I think it's worth working through this problem step by step to see all the axioms that need to be present in order to make this inference, and to do this in OWL DL. You didn't mention Protégé, but it's a very convenient OWL editor, and makes writing these axioms much easier. I'll show the final OWL (in RDF/XML and Turtle) at the end, too.
To represent just one instance, I'd declare a class Voters which has Alice, Bill, Cindy, and Dan as members, and then assert that those individuals are distinct:
Now, to relate each Voter to their vote, we can introduce a hasVote property with domain Voter and the enumerated range containing the strings, "yes", and "no".
We still need something that relates to the four Voters, to tie them together. Conceptually, this is the voting event in which the only participants were Alice, Bill, Cindy, and Dan, and in which each voter has only one vote. Let's introduce a class VotingEvent and an object property hasVoter which relates a VotingEvent to its participants. Now, there is some voting event, for which we'll introduce an individual votingEvent1. We'll assert that its participants are Alice, Bill, Cindy, and Dan, and only those, and that every voter in this event has exactly one vote. We also add two type constraints that say that the event has exactly 2 "yes" voters. This is sufficient, since the requirements that there are only the four enumerated voters, that they are distinct, that each has exactly one vote, and that each vote is either "yes" or "no", and the implicit knowledge that "yes" and "no" are distinct strings, is enough to ensure that the remaining two votes must be "no" votes.
Now, if we finally assert that Alice and Bill cast "yes" votes,
there is enough to infer with a reasoner that Cindy and Dan cast "no" votes, as we can see by running a DL query in Protégé:
Neither the Turtle nor RDF/XML serializations are particularly nice to look at, but I've attached them at the end, for easy copying and pasting. Now, this is a suitable representation for a single voting event, but note that we introduced a voting event in order to have something to which we added the restrictions about the four voters and the values of their votes. However, if there were multiple voting events, and some voters participated in more than one event, the simple restriction that a voter has exactly one vote is problematic because the voter might vote "yes" in one event and "no" in another. The "Voter x cast a vote of y in event z" is a tertiary relation, and really needs to be represented as such if multiple events are going to be present. The W3C Working Group Note, Defining N-ary Relations on the Semantic Web describes some approaches for this, but the basic idea is that you'd define a class whose members represent individuals cast votes, and are related to the voting event, the voter, and the vote cast. You can still write the appropriate restrictions for this kind of reasoning, though they'll be a little bit more complicated, probably involving property chains or nested class expressions.
Turtle Serialization
#prefix : <http://example.org/voters#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix voters: <http://example.org/voters#> .
voters:Voter a owl:Class .
voters:VotingEvent a owl:Class .
voters:hasVote a owl:DatatypeProperty ;
rdfs:domain voters:Voter ;
rdfs:range [ a rdfs:Datatype ;
owl:oneOf [ a rdf:List ;
rdf:first "no" ;
rdf:rest [ a rdf:List ;
rdf:first "yes" ;
rdf:rest ()
]
]
] .
voters:Dan a owl:NamedIndividual , voters:Voter .
<http://example.org/voters>
a owl:Ontology .
voters:Alice a owl:NamedIndividual , voters:Voter ;
voters:hasVote "yes" .
voters:Bill a owl:NamedIndividual , voters:Voter ;
voters:hasVote "yes" .
voters:Cindy a owl:NamedIndividual , voters:Voter .
voters:hasVoter a owl:ObjectProperty ;
rdfs:domain voters:VotingEvent ;
rdfs:range voters:Voter .
voters:votingEvent1 a owl:NamedIndividual , voters:VotingEvent ;
a [ a owl:Restriction ;
owl:onClass [ a owl:Restriction ;
owl:hasValue "yes" ;
owl:onProperty voters:hasVote
] ;
owl:onProperty voters:hasVoter ;
owl:qualifiedCardinality "2"^^xsd:nonNegativeInteger
] ;
a [ a owl:Restriction ;
owl:allValuesFrom [ a owl:Class ;
owl:oneOf ( voters:Dan voters:Bill voters:Cindy voters:Alice )
] ;
owl:onProperty voters:hasVoter
] ;
a [ a owl:Restriction ;
owl:allValuesFrom [ a owl:Restriction ;
owl:onDataRange xsd:string ;
owl:onProperty voters:hasVote ;
owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger
] ;
owl:onProperty voters:hasVoter
] ;
voters:hasVoter voters:Alice , voters:Bill , voters:Cindy , voters:Dan .
[ a owl:AllDifferent ;
owl:distinctMembers ( voters:Alice voters:Bill voters:Cindy voters:Dan )
] .
RDF/XML Serialization
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:voters="http://example.org/voters#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://example.org/voters"/>
<owl:Class rdf:about="http://example.org/voters#Voter"/>
<owl:Class rdf:about="http://example.org/voters#VotingEvent"/>
<owl:ObjectProperty rdf:about="http://example.org/voters#hasVoter">
<rdfs:range rdf:resource="http://example.org/voters#Voter"/>
<rdfs:domain rdf:resource="http://example.org/voters#VotingEvent"/>
</owl:ObjectProperty>
<owl:DatatypeProperty rdf:about="http://example.org/voters#hasVote">
<rdfs:domain rdf:resource="http://example.org/voters#Voter"/>
<rdfs:range>
<rdfs:Datatype>
<owl:oneOf>
<rdf:List>
<rdf:first>no</rdf:first>
<rdf:rest>
<rdf:List>
<rdf:first>yes</rdf:first>
<rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
</rdf:List>
</rdf:rest>
</rdf:List>
</owl:oneOf>
</rdfs:Datatype>
</rdfs:range>
</owl:DatatypeProperty>
<owl:AllDifferent>
<owl:distinctMembers rdf:parseType="Collection">
<owl:NamedIndividual rdf:about="http://example.org/voters#Alice">
<rdf:type rdf:resource="http://example.org/voters#Voter"/>
<voters:hasVote>yes</voters:hasVote>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://example.org/voters#Bill">
<rdf:type rdf:resource="http://example.org/voters#Voter"/>
<voters:hasVote>yes</voters:hasVote>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://example.org/voters#Cindy">
<rdf:type rdf:resource="http://example.org/voters#Voter"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://example.org/voters#Dan">
<rdf:type rdf:resource="http://example.org/voters#Voter"/>
</owl:NamedIndividual>
</owl:distinctMembers>
</owl:AllDifferent>
<owl:NamedIndividual rdf:about="http://example.org/voters#votingEvent1">
<rdf:type rdf:resource="http://example.org/voters#VotingEvent"/>
<rdf:type>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/voters#hasVoter"/>
<owl:onClass>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/voters#hasVote"/>
<owl:hasValue>yes</owl:hasValue>
</owl:Restriction>
</owl:onClass>
<owl:qualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"
>2</owl:qualifiedCardinality>
</owl:Restriction>
</rdf:type>
<rdf:type>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/voters#hasVoter"/>
<owl:allValuesFrom>
<owl:Class>
<owl:oneOf rdf:parseType="Collection">
<owl:NamedIndividual rdf:about="http://example.org/voters#Dan"/>
<owl:NamedIndividual rdf:about="http://example.org/voters#Bill"/>
<owl:NamedIndividual rdf:about="http://example.org/voters#Cindy"/>
<owl:NamedIndividual rdf:about="http://example.org/voters#Alice"/>
</owl:oneOf>
</owl:Class>
</owl:allValuesFrom>
</owl:Restriction>
</rdf:type>
<rdf:type>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/voters#hasVoter"/>
<owl:allValuesFrom>
<owl:Restriction>
<owl:onProperty rdf:resource="http://example.org/voters#hasVote"/>
<owl:qualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"
>1</owl:qualifiedCardinality>
<owl:onDataRange rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
</owl:Restriction>
</owl:allValuesFrom>
</owl:Restriction>
</rdf:type>
<voters:hasVoter rdf:resource="http://example.org/voters#Alice"/>
<voters:hasVoter rdf:resource="http://example.org/voters#Bill"/>
<voters:hasVoter rdf:resource="http://example.org/voters#Cindy"/>
<voters:hasVoter rdf:resource="http://example.org/voters#Dan"/>
</owl:NamedIndividual>
</rdf:RDF>
You do this with an OWL ontology, but it's complicated. First, you have to model the fact that a person only has one vote. Second, you must know that John, Bob, Mary, and Carol voted. You have to know that there have been 2 "yes", and 2 "no". You have to know that Bob and John voted "no", and that they are two people, not one with a pseudonym. You have to know that Mary and Carol are different from John and Bob. And so, in Turtle:
:votes a owl:FunctionalProperty .
:John :votes "no" .
:Bob :votes "no";
owl:differentFrom :John .
:Mary a [
owl:onProperty :votes;
owl:minCardinality 1
];
owl:differentFrom :Bob, :John .
:Carol a [
owl:onProperty :votes;
owl:minCardinality 1
];
owl:differentFrom :Bob, :John .
_:someone a [ owl:onProperty :votes; owl:hasValue "no" ];
owl:differentFrom _:someoneelse .
_:someoneelse a [ owl:onProperty :votes; owl:hasValue "no" ] .
_:anotherone a [ owl:onProperty :votes; owl:hasValue "yes" ];
owl:differentFrom _:anotheroneelse .
_:anotheroneelse a [owl:onProperty :votes; owl:hasValue "yes" ] .
[ owl:onProperty :votes; owl:hasValue "no" ]
owl:oneOf ( _:someone _:someoneelse ) .
[ owl:onProperty :votes; owl:hasValue "yes" ]
owl:oneOf ( _:anotherone _:anotheroneelse ) .
The real difficulty here is to express that there are 2 "yes" and 2 "no". I've made it compact, and so it's not in OWL 2 DL, but it should be possible to make it an OWL 2 DL ontology.
Note that this does not allow modelling multiple polls or ballots. An even more complicated solution would be required (but still doable).

how to relate an individual with a combination of individuals?

I have an ontology that contains plants and diseases and a property treat (a plant treats diseases). I have a lot of plants and diseases, but now I want to add a disease that is treatable by a combination of two or more plants. For instance, how can I represent the following sentence?
Disease X is treatable by the combination of plant A and plant B, but not by plant A or plant B alone.
I've been thinking to obtain this using a reasoner, but I have no idea how.
It sounds like you have, at the moment, an ontology with a classes Disease and Plant, and a property treats with domain Plant and range Disease. As I understand it, the problem is that what should treat some Diseases are not individual Plants, but rather combinations of them. In these cases, we might say that a plant is used in the treatment of a disease, but does not, itself, treat the disease. It is probably reasonable to say, too, that if a plant, by itself, treats a disease, then it also is used in the treatment of a disease.
So, you have a class of individuals that you haven't considered before, that is combinations of plants, so why not introduce a class PlantCombination and a property hasComponent that relates PlantCombinations to the plants in the combination? You can also add a restriction that says that each plant combination has at least two plants, if you like, by saying PlantCombination SubClassOf hasComponent min 2 Plant. Since both Plants and PlantCombinations can treat Diseases, you'll want to change the domain of treats to be Plant or PlantCombination. To ensure that a reasoner can infer that if plant82 treats disease92 then plant82 isUsedToTreat disease92, you can assert that treats SubPropertyOf isUsedToTreat. (This will also mean that a plant combination that treats a disease is also used to treat that disease.) To ensure that when a combination with a component plant23 treats a disease, that plant23 is used to treat the disease, you can add the assertion that inverse(hasComponent) o treats SubPropertyOf isUsedToTreat. Here's an ontology that does just that:
N3 Format
#prefix : <http://www.example.org/plantsAndDiseases#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
<http://www.example.org/plantsAndDiseases>
a owl:Ontology .
:Plant
a owl:Class .
:Disease
a owl:Class .
:PlantCombination
a owl:Class ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:minQualifiedCardinality
"2"^^xsd:nonNegativeInteger ;
owl:onClass :Plant ;
owl:onProperty :hasComponent
] .
:hasComponent
a owl:ObjectProperty ;
rdfs:domain :PlantCombination ;
rdfs:range :Plant .
:isUsedToTreat
a owl:ObjectProperty ;
rdfs:comment "X isUsedToTreat Y means that X is used in the treatment of Y. X may either treat Y, or may be a component of a combination that treats Y." ;
rdfs:domain
[ a owl:Class ;
owl:unionOf (:Plant :PlantCombination)
] ;
rdfs:range :Disease ;
owl:propertyChainAxiom
([ owl:inverseOf :hasComponent
] :treats) .
:treats
a owl:ObjectProperty ;
rdfs:comment "X treats Y means that X is a sufficient treatment for Y." ;
rdfs:domain
[ a owl:Class ;
owl:unionOf (:Plant :PlantCombination)
] ;
rdfs:range :Disease ;
rdfs:subPropertyOf :isUsedToTreat .
OWL Functional Syntax
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)
Ontology(<http://www.example.org/plantsAndDiseases>
Declaration(Class(<http://www.example.org/plantsAndDiseases#Disease>))
Declaration(Class(<http://www.example.org/plantsAndDiseases#Plant>))
Declaration(Class(<http://www.example.org/plantsAndDiseases#PlantCombination>))
SubClassOf(<http://www.example.org/plantsAndDiseases#PlantCombination> ObjectMinCardinality(2 <http://www.example.org/plantsAndDiseases#hasComponent> <http://www.example.org/plantsAndDiseases#Plant>))
Declaration(ObjectProperty(<http://www.example.org/plantsAndDiseases#hasComponent>))
ObjectPropertyDomain(<http://www.example.org/plantsAndDiseases#hasComponent> <http://www.example.org/plantsAndDiseases#PlantCombination>)
ObjectPropertyRange(<http://www.example.org/plantsAndDiseases#hasComponent> <http://www.example.org/plantsAndDiseases#Plant>)
Declaration(ObjectProperty(<http://www.example.org/plantsAndDiseases#isUsedToTreat>))
AnnotationAssertion(rdfs:comment <http://www.example.org/plantsAndDiseases#isUsedToTreat> "X isUsedToTreat Y means that X is used in the treatment of Y. X may either treat Y, or may be a component of a combination that treats Y.")
ObjectPropertyDomain(<http://www.example.org/plantsAndDiseases#isUsedToTreat> ObjectUnionOf(<http://www.example.org/plantsAndDiseases#PlantCombination> <http://www.example.org/plantsAndDiseases#Plant>))
ObjectPropertyRange(<http://www.example.org/plantsAndDiseases#isUsedToTreat> <http://www.example.org/plantsAndDiseases#Disease>)
Declaration(ObjectProperty(<http://www.example.org/plantsAndDiseases#treats>))
AnnotationAssertion(rdfs:comment <http://www.example.org/plantsAndDiseases#treats> "X treats Y means that X is a sufficient treatment for Y.")
SubObjectPropertyOf(<http://www.example.org/plantsAndDiseases#treats> <http://www.example.org/plantsAndDiseases#isUsedToTreat>)
ObjectPropertyDomain(<http://www.example.org/plantsAndDiseases#treats> ObjectUnionOf(<http://www.example.org/plantsAndDiseases#PlantCombination> <http://www.example.org/plantsAndDiseases#Plant>))
ObjectPropertyRange(<http://www.example.org/plantsAndDiseases#treats> <http://www.example.org/plantsAndDiseases#Disease>)
SubObjectPropertyOf(ObjectPropertyChain(ObjectInverseOf(<http://www.example.org/plantsAndDiseases#hasComponent>) <http://www.example.org/plantsAndDiseases#treats>) <http://www.example.org/plantsAndDiseases#isUsedToTreat>)
)
Alternative to Joshua's answer: You can represent diseases and plants as OWL classes, as here you refer to sets of plants (not particular instances, which you would find in the nature). You can then link classes with existential restrictions (some - common pattern in biology).
You need also to introduce a supplementary step in your modelling, as mentioned: Plants can be for example ingredients of treatments, diseases being treatable by treatments.
Then if you consider the following commented (#) ontology (Manchester syntax), I describe the axioms for the modelling. You can save the file and open it with Protege.
Prefix: xsd: <http://www.w3.org/2001/XMLSchema#>
Prefix: owl: <http://www.w3.org/2002/07/owl#>
Prefix: : <http://www.example.org/demo.owl#>
Prefix: xml: <http://www.w3.org/XML/1998/namespace>
Prefix: rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
Prefix: rdfs: <http://www.w3.org/2000/01/rdf-schema#>
Ontology: <http://www.example.org/demo.owl>
ObjectProperty: has-ingredient
ObjectProperty: treatableBy
Class: owl:Thing
Class: PlantA
SubClassOf:
Plant
Class: Treatment
#Your treatment obtained by mixing some
#of the plant B and some of the plant A
Class: TreatmentAB
SubClassOf:
Treatment,
(has-ingredient some PlantA)
and (has-ingredient some PlantB)
Class: PlantB
SubClassOf:
Plant
#This treatment has ingredient the plant A
Class: TreatmentA
SubClassOf:
has-ingredient some PlantA,
Treatment
#This treatment is made from plant B (among other things)
Class: TreatmentB
SubClassOf:
Treatment,
has-ingredient some PlantB
Class: Disease
Class: Plant
# This disease is treatable by the TreatmentAB
Class: DiseaseA
SubClassOf:
treatableBy some TreatmentAB,
Disease
Class: DiseaseB
SubClassOf:
treatableBy some TreatmentB,
Disease
Now if we were reasoning over the ontology and ask for the subclasses of treatableBy some TreatmentA we wouldn't get any class. The expression treatableBy some TreatmentAB returns DiseaseA as expected.

OWL Ontology: Represent increasing number, like first, second, third

I have a question about an OWL ontology that I am making. I have a class that is actually an ID class and I would like to have instances: first, second, third etc.
The first solution that I have figured is creating individuals {first, second, third etc} for this class, but then I have to write a huge number of individuals.
The other solution is to create a data property that will be connected with my class that has type "integer".
The second solution looks more appropriate but the thing is that I can't represent the word "first", just the number 1.
Do you know how I can do that?
You could create a class of ordinals that are uniquely identified by an integer, like so (in Turtle syntax):
:hasPosition a owl:DatatypeProperty, owl:FunctionalProperty ;
rdfs:range xsd:integer .
:Ordinal a owl:Class ;
rdfs:subClassOf [
a owl:Restriction ;
owl:onProperty :hasPosition ;
owl:someValuesFrom :integer
] ;
owl:hasKey ( :hasPosition ) .
Note the use of owl:hasKey (introduced in OWL 2) which means that the value of :hasPosition identifies a unique instance. The property is functional so that an instance cannot have two distinct positions.

Resources