Two Standards Come Pre-packaged with Owlready2
We introduce OWL (knowledge graph) reasoners in this installment of the Cooking with Python and KBpedia series. A reasoner has two purposes. First, based on deductive reasoning, a reasoner can infer new class and property assignments that are logically entailed by the assertions in an ontology (that is, from its axioms) but not otherwise explicitly stated. Once inferred, these additional assignments can be written to an inferred version of the ontology for faster lookups and analysis. Second, reasoners can evaluate the stated axioms to determine if the ontology is consistent or satisfiable. This second purpose is a key step when building or modifying a knowledge graph to ensure that illogical assertions are not introduced into the system. Reasoners thus often have explanation routines that point out where the inconsistencies or problems occur, thus helping the analyst to fix the errors before committing to productive use. In later installments we will focus especially on these coherency tests when we discuss the build procedures for KBpedia.
Consistency is when none of the assertions (axioms) in the knowledge graph contradicts another one. If there is a contradiction the graph is termed to be inconsistent. Satisfiability individually evaluates the classes in the graph and checks to see if they can have instances without contradicting other asserted axioms. Unsatisfiability indicates there is a conflicting or missing assignment that needs to be corrected. It is a particularly useful check when there are disjoint assertions made between classes, one of the design pillars of KBpedia.
Owlready2 is distributed with two OWL reasoners:
- HermiT, developed by the department of Computer Science of the University of Oxford, and
- Pellet, a reasoner developed specifically to support the OWL language.
Both HermiT and Pellet are written in Java, so require access to a JVM on your system. If you have difficulty running these systems it is likely because you: 1) do not have a recent version of Java installed on your system; or 2) do not have a proper PATH
statement in your environmental variables to find the Java executable. If you encounter such problems, please consult third-party sources to get Java properly configured for your system before continuing with this installment.
Test Ontology
To make sure that your system is configured properly, go ahead and shift+enter
or Run this cell that enters a small example ontology from the owlready2 documentation:
from owlready2 import *
= get_ontology("http://test.org/onto.owl")
onto
with onto:
class Drug(Thing):
def take(self): print("I took a drug")
class ActivePrinciple(Thing):
pass
class has_for_active_principle(Drug >> ActivePrinciple):
= "active_principles"
python_name
class Placebo(Drug):
= [Drug & Not(has_for_active_principle.some(ActivePrinciple))]
equivalent_to def take(self): print("I took a placebo")
class SingleActivePrincipleDrug(Drug):
= [Drug & has_for_active_principle.exactly(1, ActivePrinciple)]
equivalent_to def take(self): print("I took a drug with a single active principle")
class DrugAssociation(Drug):
= [Drug & has_for_active_principle.min(2, ActivePrinciple)]
equivalent_to def take(self): print("I took a drug with %s active principles" % len(self.active_principles))
= ActivePrinciple("acetaminophen")
acetaminophen = ActivePrinciple("amoxicillin")
amoxicillin = ActivePrinciple("clavulanic_acid")
clavulanic_acid
AllDifferent([acetaminophen, amoxicillin, clavulanic_acid])
= Drug(active_principles = [acetaminophen])
drug1 = Drug(active_principles = [amoxicillin, clavulanic_acid])
drug2 = Drug(active_principles = [])
drug3
close_world(Drug)
Then, run the HermiT reasoner with the single command:
sync_reasoner()
* Owlready2 * Running HermiT...
java -Xmx2000M -cp C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit;C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit\HermiT.jar org.semanticweb.HermiT.cli.CommandLine -c -O -D -I file:///C:/Users/mike/AppData/Local/Temp/tmpbnxf7755
* Owlready2 * HermiT took 0.4851553440093994 seconds
* Owlready * Reparenting onto.drug2: {onto.Drug} => {onto.DrugAssociation}
* Owlready * Reparenting onto.drug1: {onto.Drug} => {onto.SingleActivePrincipleDrug}
* Owlready * Reparenting onto.drug3: {onto.Drug} => {onto.Placebo}
* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)
The feedback you get to screen should indicate that you are ‘Reparenting’ the three drugs from one class (Drug
) to their appropriate sublasses. By the way, you could also place this argument in the command to turn off the debug reports to screen: $ sync_reasoner(debug = 0)
.
You can also confirm this move for drug2
:
print("drug2 new Classes:", drug2.__class__)
drug2 new Classes: onto.DrugAssociation
And, then, in the next three cells, confirm how you took those three drugs:
drug1.take()
I took a drug with a single active principle
drug2.take()
I took a drug with 2 active principles
drug3.take()
I took a placebo
And, last, in the next two cells discover if any inconsistent classes remain (they do not), which is equivalent to a class being assigned to the Nothing
class in OWL:
list(default_world.inconsistent_classes())
[]
if Nothing in Drug.equivalent_to:
print("Drug is inconsistent!")
General Load Method
OK, so now we see the HermiT reasoner is configured properly and working, we are now ready to test our KBpedia knowledge graph. Go ahead and select Kernel → Restart & Clear Output from the main menu to begin the next activities from a clean slate.
Then execute what has become our standard load procedure:
#
) out.= 'C:/1-PythonProjects/kbpedia/sandbox/kbpedia_reference_concepts.owl'
main # main = 'https://raw.githubusercontent.com/Cognonto/CWPK/master/sandbox/builds/ontologies/kbpedia_reference_concepts.owl'
= 'http://www.w3.org/2004/02/skos/core'
skos_file = 'C:/1-PythonProjects/kbpedia/sandbox/kko.owl'
kko_file # kko_file = 'https://raw.githubusercontent.com/Cognonto/CWPK/master/sandbox/builds/ontologies/kko.owl'
from owlready2 import *
= World()
world = world.get_ontology(main).load()
kb = kb.get_namespace('http://kbpedia.org/kko/rc/')
rc
= world.get_ontology(skos_file).load()
skos
kb.imported_ontologies.append(skos)
= world.get_ontology(kko_file).load()
kko kb.imported_ontologies.append(kko)
HermiT Reasoner
We again invoke the HermiT reasoner:
sync_reasoner()
* Owlready2 * Running HermiT...
java -Xmx2000M -cp C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit;C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit\HermiT.jar org.semanticweb.HermiT.cli.CommandLine -c -O -D -I file:///C:/Users/mike/AppData/Local/Temp/tmpxglvdub2
* Owlready2 * HermiT took 0.42046189308166504 seconds
* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)
There is also an argument to infer_property_values = True
:
= True) sync_reasoner(infer_property_values
* Owlready2 * Running HermiT...
java -Xmx2000M -cp C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit;C:\1-PythonProjects\Python\lib\site-packages\owlready2\hermit\HermiT.jar org.semanticweb.HermiT.cli.CommandLine -c -O -D -I file:///C:/Users/mike/AppData/Local/Temp/tmpxkc92ws4 -Y
* Owlready2 * HermiT took 0.416165828704834 seconds
* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)
We see that the ontology is consistent, which we can confirm with this additional command:
list(world.inconsistent_classes())
[]
Pellet Reasoner
The second of our reasoners, Pellet, operates under a similar set of arguments. We invoke Pellet through the modified reasoner command:.
sync_reasoner_pellet()
* Owlready2 * Running Pellet...
java -Xmx2000M -cp C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\antlr-3.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\antlr-runtime-3.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\aterm-java-1.6.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\commons-codec-1.6.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\httpclient-4.2.3.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\httpcore-4.2.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jcl-over-slf4j-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-arq-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-core-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-iri-0.9.5.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-tdb-0.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jgrapht-jdk1.5.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\log4j-1.2.16.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\owlapi-distribution-3.4.3-bin.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\pellet-2.3.1.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\slf4j-api-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\slf4j-log4j12-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\xercesImpl-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\xml-apis-1.4.01.jar pellet.Pellet realize --loader Jena --input-format N-Triples --ignore-imports C:\Users\mike\AppData\Local\Temp\tmp7_rotl4_
* Owlready2 * Pellet took 1.017836093902588 seconds
* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)
Pellet, too, is configured to run in a debug mode. If you wish, you may turn it off with $ sync_reasoner(debug = 0)
.
Like HermiT we can also infer_property_values
. But, different than HermiT, we may also infer_data_property_values = True
using Pellet:
= True, infer_data_property_values = True) sync_reasoner_pellet(infer_property_values
* Owlready2 * Running Pellet...
java -Xmx2000M -cp C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\antlr-3.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\antlr-runtime-3.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\aterm-java-1.6.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\commons-codec-1.6.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\httpclient-4.2.3.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\httpcore-4.2.2.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jcl-over-slf4j-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-arq-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-core-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-iri-0.9.5.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jena-tdb-0.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\jgrapht-jdk1.5.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\log4j-1.2.16.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\owlapi-distribution-3.4.3-bin.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\pellet-2.3.1.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\slf4j-api-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\slf4j-log4j12-1.6.4.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\xercesImpl-2.10.0.jar;C:\1-PythonProjects\Python\lib\site-packages\owlready2\pellet\xml-apis-1.4.01.jar pellet.Pellet realize --loader Jena --input-format N-Triples --infer-prop-values --infer-data-prop-values --ignore-imports C:\Users\mike\AppData\Local\Temp\tmpcr2dw8yi
* Owlready2 * Pellet took 0.6863009929656982 seconds
* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)
list(world.inconsistent_classes())
[]
SWRL
As long as we are introducing these capabilities, we should also mention that Owlready2 also supports the use of SWRL (the Semantic Web Rule Language) “if . . . then” type statements. To the best of my knowledge, Owlready2 supports all of the standard SWRL constructs. It is also possible to mix Python and OWL code together, but that, too, is a topic we will not be addressing further in this CWPK series.
Save and Exit
When we are finished with our tests, we can File → Save and Checkpoint, Rename our output file, or specify it at the command line:
file = 'files/kbpedia_reference_concepts-pellet.owl', format = 'rdfxml') kb.save(
Additional Documentation
Here are links to appropriate Owlready2 documentation:
*.ipynb
file. It may take a bit of time for the interactive option to load.
Thanks this article was very helpful!