OWL-RL
OWL-RL is a Python library that provides a simple implementation of the OWL2 RL Profile, as well as basic RDFS inference, on top of RDFLib. It performs mechanical forward chaining to compute the deductive closure of RDF graphs. The current version is 7.1.4, and it is actively maintained with a focus on semantic web inference capabilities.
Warnings
- breaking OWL-RL version 7.x, following RDFLib's dependency updates, now requires Python 3.9 or higher. Older projects using Python 2.7 or earlier Python 3 versions (e.g., 3.5, 3.6) will need to upgrade their Python environment or use an older `owlrl` version.
- breaking In version 5.1.0, the primary module for the library was renamed from `RDFClosure` to `owlrl`. If you are migrating an older codebase, import statements like `from RDFClosure import DeductiveClosure` must be updated to `from owlrl import DeductiveClosure`.
- gotcha The `DeductiveClosure` class does not automatically interpret `owl:imports` statements. Any imported ontologies must be explicitly loaded and merged into the graph (e.g., using `owlrl.interpret_owl_imports`) before calling `expand()` for the inference process to consider them.
- gotcha RDFLib's default datatype handling may not meet the stricter requirements of OWL 2 RL, potentially leading to incorrect inferences for complex datatypes. `owlrl` provides improved datatype conversion routines, which can be explicitly enabled.
- gotcha A known bug in RDFLib's Turtle parser can cause exceptions when parsing abbreviated double datatypes (e.g., `1.234E56`). It's advisable to avoid this specific literal syntax in your Turtle files if you encounter parsing errors.
- gotcha On Windows systems, if both the `owlrl` package and an `owlrl.py` command-line script are present and accessible in `PYTHON_PATH`, attempting to `from owlrl import convert_graph` (an older entry point) could lead to an import collision, as Python might incorrectly try to import from the script file.
Install
-
pip install owlrl
Imports
- DeductiveClosure
from RDFClosure import DeductiveClosure
from owlrl import DeductiveClosure
- RDFS_Semantics
from owlrl import RDFS_Semantics
- OWLRL_Semantics
from owlrl import OWLRL_Semantics
- Graph
from rdflib import Graph
Quickstart
from rdflib import Graph, Literal, Namespace, RDF, RDFS
from owlrl import DeductiveClosure, OWLRL_Semantics
# Define a simple namespace for demonstration
ex = Namespace("http://example.org/ontology#")
# Create an RDFLib graph
graph = Graph()
graph.bind("ex", ex)
# Add some initial triples (asserted facts)
graph.add((ex.Person, RDF.type, RDFS.Class))
graph.add((ex.Student, RDFS.subClassOf, ex.Person))
graph.add((ex.John, RDF.type, ex.Student))
# Add a rule that says if someone is a Person, they are also an Agent
graph.add((ex.Agent, RDF.type, RDFS.Class))
graph.add((ex.Person, RDFS.subClassOf, ex.Agent))
print(f"Graph size before OWL RL expansion: {len(graph)}")
# Initialize and run the OWL 2 RL deductive closure
closure = DeductiveClosure(OWLRL_Semantics)
closure.expand(graph)
# The graph now contains inferred triples, e.g., John is a Person, and also an Agent
print(f"Graph size after OWL RL expansion: {len(graph)}")
# Check for an inferred triple
if (ex.John, RDF.type, ex.Agent) in graph:
print("Inferred: John is an Agent.")
# You can also run RDFS inference separately
rdfs_graph = Graph()
rdfs_graph.bind("ex", ex)
rdfs_graph.add((ex.Teacher, RDFS.subClassOf, ex.Person))
rdfs_graph.add((ex.Jane, RDF.type, ex.Teacher))
print(f"\nGraph size before RDFS expansion: {len(rdfs_graph)}")
from owlrl import RDFS_Semantics
rdfs_closure = DeductiveClosure(RDFS_Semantics)
rdfs_closure.expand(rdfs_graph)
print(f"Graph size after RDFS expansion: {len(rdfs_graph)}")
if (ex.Jane, RDF.type, ex.Person) in rdfs_graph:
print("Inferred: Jane is a Person.")