owlrl¶
This module is a brute force implementation of the ‘finite’ version of RDFS semantics and of OWL 2 RL on the top of RDFLib (with some caveats, see below). Some extensions to these are also implemented.
Brute force means that, in all cases, simple forward chaining rules are used to extend (recursively) the incoming graph
with all triples that the rule sets permit (ie, the “deductive closure” of the graph is computed).
There is an extra options whether the axiomatic triples are added to the graph (prior to the forward chaining step).
These, typically set the domain and range for properties or define some core classes.
In the case of RDFS, the implementation uses a ‘finite’ version of the axiomatic triples only (as proposed, for example,
by Herman ter Horst). This means that it adds only those rdf:_i
type predicates that do appear in the original graph,
thereby keeping this step finite. For OWL 2 RL, OWL 2 does not define axiomatic triples formally; but they can be
deduced from the OWL 2 RDF Based Semantics document and are listed in Appendix 6 (though informally).
Note
This implementation adds only those triples that refer to OWL terms that are meaningful for the OWL 2 RL case.
Package Entry Points¶
The main entry point to the package is via the DeductiveClosure
class. This class should be
initialized to control the parameters of the deductive closure; the forward chaining is done via the
L{expand<DeductiveClosure.expand>} method.
The simplest way to use the package from an RDFLib application is as follows:
graph = Graph() # creation of an RDFLib graph
...
... # normal RDFLib application, eg, parsing RDF data
...
DeductiveClosure(OWLRL_Semantics).expand(graph) # calculate an OWL 2 RL deductive closure of graph
# without axiomatic triples
The first argument of the DeductiveClosure
initialization can be replaced by other classes, providing different
types of deductive closure; other arguments are also possible. For example:
DeductiveClosure(OWLRL_Extension, rdfs_closure = True, axiomatic_triples = True, datatype_axioms = True).expand(graph)
This will calculate the deductive closure including RDFS and some extensions to OWL 2 RL, and with all possible axiomatic triples added to the graph (this is about the maximum the package can do…)
The same instance of DeductiveClosure
can be used for several graph expansions. In other words, the
expand function does not change any state.
For convenience, a second entry point to the package is provided in the form of a function called
convert_graph()
, that expects a directory with various options, including a file name. The function
parses the file, creates the expanded graph, and serializes the result into RDF/XML or Turtle. This function is
particularly useful as an entry point for a CGI call (where the HTML form parameters are in a directory) and is easy to
use with a command line interface. The package distribution contains an example for both.
There are major closure type (ie, semantic closure possibilities); these can be controlled through the appropriate
parameters of the DeductiveClosure
class:
- using the
RDFS_Semantics
class, implementing the RDFS semantics.
- using the
OWLRL.OWLRL_Semantics
class, implementing the OWL 2 RL.
- using
CombinedClosure.RDFS_OWLRL_Semantics
class, implementing a combined semantics of RDFS semantics and OWL 2 RL.
In all three cases there are other dimensions that can control the exact closure being generated:
- for convenience, the so called axiomatic triples (see, eg, the axiomatic triples in RDFS are, by default, I{not} added to the graph closure to reduce the number of generated triples. These can be controlled through a separate initialization argument.
- similarly, the axiomatic triples for D-entailment are separated.
Some Technical/implementation aspects¶
The core processing is done in the in the Closure.Core
class, which is subclassed by the
RDFSClosure.RDFS_Semantics
and the OWLRL.OWLRL_Semantics
classes (these two are then, on their turn,
subclassed by the CombinedClosure.RDFS_OWLRL_Semantics
class). The core implements the core functionality of
cycling through the rules, whereas the rules themselves are defined and implemented in the subclasses. There are also
methods that are executed only once either at the beginning or at the end of the full processing cycle. Adding axiomatic
triples is handled separately, which allows a finer user control over these features.
Literals must be handled separately. Indeed, the functionality relies on ‘extended’ RDF graphs, that allows literals
to be in a subject position, too. Because RDFLib does not allow that, processing begins by exchanging all literals in
the graph for bnodes (identical literals get the same associated bnode). Processing occurs on these bnodes; at the end
of the process all these bnodes are replaced by their corresponding literals if possible (if the bnode occurs in a
subject position, that triple is removed from the resulting graph). Details of this processing is handled in the
separate Literals.LiteralProxies
class.
The OWL specification includes references to datatypes that are not in the core RDFS specification, consequently not directly implemented by RDFLib. These are added in a separate module of the package.
Problems with Literals with datatypes¶
The current distribution of RDFLib is fairly poor in handling datatypes, particularly in checking whether a lexical form of a literal is “proper” as for its declared datatype. A typical example is:
"-1234"^^xsd:nonNegativeInteger
which should not be accepted as valid literal. Because the requirements of OWL 2 RL are much stricter in this respect,
an alternative set of datatype handling (essentially, conversions) had to be implemented (see the XsdDatatypes
module).
The DeductiveClosure
class has an additional instance variable whether
the default RDFLib conversion routines should be exchanged against the new ones. If this flag is set to True and
instance creation (this is the default), then the conversion routines are set back to the originals once the expansion
is complete, thereby avoiding to influence older application that may not work properly with the new set of conversion
routines.
If the user wants to use these alternative lexical conversions everywhere in the application, then
the DeductiveClosure.use_improved_datatypes_conversions()
method can be invoked.
That method changes the conversion routines and, from that point on, all usage of DeductiveClosure
instances
will use the improved conversion methods without resetting them. Ie, the code structure can be something like:
DeductiveClosure().use_improved_datatypes_conversions()
... RDFLib application
DeductiveClosure().expand(graph)
...
The default situation can be set back using the
DeductiveClosure.use_rdflib_datatypes_conversions()
call.
It is, however, not required to use these methods at all. I.e., the user can use:
DeductiveClosure(improved_datatypes=False).expand(graph)
which will result in a proper graph expansion except for the datatype specific comparisons which will be incomplete.
- Requires:
- RDFLib, 4.0.0 and higher.
License: This software is available for use under the W3C Software License
Organization: World Wide Web Consortium
Author: Ivan Herman
Functions
convert_graph (options[, closureClass]) |
Entry point for external scripts (CGI or command line) to parse an RDF file(s), possibly execute OWL and/or RDFS closures, and serialize back the result in some format. |
interpret_owl_imports (iformat, graph) |
Interpret the owl import statements. |
return_closure_class (owl_closure, …[, …]) |
Return the right semantic extension class based on three possible choices (this method is here to help potential users, the result can be fed into a DeductiveClosure instance at initialization). |
Classes
DeductiveClosure (closure_class[, …]) |
Entry point to generate the deductive closure of a graph. |