Introduction
The materializer generates triples by applying a set of rules to the current triples in the triple store and then places the resulting triples back in the triple store.
The materializer differs from the RDFS++ reasoner in that the materializer computes all inferred triples at once and stores them whereas the RDFS++ reasoner computes inferred triples dynamically and does not store them in the triple store.
If the triple store is changed via additions or deletions then materialization may have to be run again in order that the triple store contain the correct set of materialized triples.
The rules that the materializer uses are subset of the OWL 2 RL rules described at http://www.w3.org/TR/2009/REC-owl2-profiles-20091027/.
OWL 2 RL is the subset of OWL 2 that is designed to support reasoners.
OWL 2 RL contains a large number of rules for generating triples and some rules for verifying that the triple store is consistent with respect to the OWL 2 RL ontology.
The Materializer implements a subset of these OWL 2 RL rules and we plan to add more rules in future versions.
Limitations
The first version has some limitations that we'll describe here. Some of those limitations will be lifted in subsequent versions.
The Materializer assumes that the triple store contains triples only in the default graph. The Materializer assumes that it is free to delete triples that have the same Subject, Predicate and Object.
After the materializer is finished the original triples will still be present and there will be a set of triples in a newly created graph. This newly created graph is a special kind of triple part that cannot be expressed in nquad format. Therefore you cannot serialize the triple store and then load it back in. This is a limitation of the current version. This aspect of graph assignment will be changed in a future version.
You can run queries over the triple store and SPARQL or Prolog will look both in the default graph and the materialized triples graph.
API
There is a AGWebView interface (see WebView, particularly the Repository Overview Page section), a Java interface (see AGMaterializer#newInstance() and AGRepositoryConnection#materialize), and a Python interface, as well as the Lisp interface described next.
materialize-entailed-triples
The main function is
materialize-entailed-triples (&key (db *db*) verbose
print-ontology
(commit 100000)
(ruleset 0 ruleset-p)
with
without
use-type-subproperty
) where
- db: specifies the triple store to materialize
- commit: should be
nilor a number. Ifnilthen the materializer will never commit (which is not a good idea if the database is large and there are many materialized triples). If commit is a number then after this many triples are added to the triple store a commit will be done, and a commit will be done when the materializer is finished. - print-ontology: will print the classes and properties found in the triple store.
- with: either "all" or a list of the sets of rules to run (details below).
- without: a list of sets of rules to not run.
- use-type-subproperty: change the implied predicate for subproperty reasoning
The symbolic names for the rulesets (which are written as string) are as follows. We'll describe what they mean in detail below
- "all"
- "same-as"
- "restriction"
- "values-from"
- "class"
- "property"
Note that "values-from" is a special set of "restriction" rules. If "restriction" is specified then you can also specify "values-from" to enable that set of restriction rules
Examples of how to specify rulesets
(materialize-entailed-triples) will add do the RDFS++ entailed triples.
(materialize-entailed-triples :with "all") will run all rules. Note that the result of this call may differ between versions of the materializer.
(materialize-entailed-triples :with '("same-as" "restriction")) run the RDFS++ reasoning as well as "same-as" and "restriction".
(materialize-entailed-triples :with '("values-from")) this is just basis RDFS++ reasoning as "restriction" was not specified as well so "values-from" is ignored.
(materialize-entailed-triples :without '("property" "values-from")) run all rules except "property" and the "values-from" part of "restriction" reasoning.
The use-type-subproperty argument changes the triple which is generated in the following way:
Given:
classA rdfs:subClassOf classB
mytype rdfs:subPropertyOf rdf:type
objX mytype classA then:
we would normally generate this triple::
objX rdf:type classB but if use-type-subproperty is true then we will instead generate this triple:
objX mytype classB delete-materialized-triples
The second function in the API is:
(delete-materialized-triples commitp) This function deletes any materialized triples in the database and returns a count of the number deleted. If commitp is true then a commit will be done after the delete.
The materialize-entailed-triples function will first call delete-materialized-triples before starting to add triples.
Materialization rule sets
The table below is from the OWL 2 RL definition. We’ve added a second column where we describe how this rule is treated by the materializer.
Rules which are not done are numbered 1, 2, or 3 or have no number at all. The numbers indicate why they aren’t done. The rules with no number have not been considered yet for inclusion in the materializer and may appear in a future version.
Rules numbered 10 or 11 have been included in the materializer. Rules numbered 10 are part of the basic RDFS++ materializer and always run. Rules numbered 11 are implemented by another part of the materializer where they are run as independent rules. If the number 11 is followed by one or more ruleset names then those rulesets must be enabled for these rules to run.
Key:
Not done:
- not done -- due to database clutter that would result. May be an option in the future.
- not done – is a consistency check and not something that materializes triples
- not done – expensive to calculate a canonical value for each literal and compare that to the canonical value of every other literal to find those that are identical. Also this would add triples with a literal as the subject which is not RDF.
Done:
10. done -- using initial RDFS++ code
11. done -- as a rule
| | notes | If | then | |
| eq-ref | 1 | T(?s, ?p, ?o) | T(?s, owl:sameAs, ?s) | |
| eq-sym | 11 same-as | T(?x, owl:sameAs, ?y) | T(?y, owl:sameAs, ?x) | |
| eq-trans | 11 same-as | T(?x, owl:sameAs, ?y) | T(?x, owl:sameAs, ?z) | |
| eq-rep-s | 11 same-as | T(?s, owl:sameAs, ?s') | T(?s', ?p, ?o) | |
| eq-rep-p | 11 same-as | T(?p, owl:sameAs, ?p') | T(?s, ?p', ?o) | |
| eq-rep-o | 11 same-as | T(?o, owl:sameAs, ?o') | T(?s, ?p, ?o') | |
| eq-diff1 | 2 | T(?x, owl:sameAs, ?y) | false | |
| eq-diff2 | 2 | T(?x, rdf:type, owl:AllDifferent) | false | for each 1 ≤ i < j ≤ n |
| eq-diff3 | 2 | T(?x, rdf:type, owl:AllDifferent) | false | for each 1 ≤ i < j ≤ n |
| | notes | if | then | |
| prp-ap | | | T(ap, rdf:type, owl:AnnotationProperty) | for each built-in annotation property of OWL 2 RL |
| prp-dom | 10 | T(?p, rdfs:domain, ?c) | T(?x, rdf:type, ?c) | |
| prp-rng | 10 | T(?p, rdfs:range, ?c) | T(?y, rdf:type, ?c) | |
| prp-fp | 10 | T(?p, rdf:type, owl:FunctionalProperty) | T(?y1, owl:sameAs, ?y2) | |
| prp-ifp | 10 | T(?p, rdf:type, owl:InverseFunctionalProperty) | T(?x1, owl:sameAs, ?x2) | |
| prp-irp | 2 | T(?p, rdf:type, owl:IrreflexiveProperty) | false | |
| prp-symp | | T(?p, rdf:type, owl:SymmetricProperty) | T(?y, ?p, ?x) | |
| prp-asyp | 2 | T(?p, rdf:type, owl:AsymmetricProperty) | false | |
| prp-trp | 11 | T(?p, rdf:type, owl:TransitiveProperty) | T(?x, ?p, ?z) | |
| prp-spo1 | 10 | T(?p1, rdfs:subPropertyOf, ?p2) | T(?x, ?p2, ?y) | |
| prp-spo2 | | T(?p, owl:propertyChainAxiom, ?x) | T(?u1, ?p, ?un+1) | |
| prp-eqp1 | 10 | T(?p1, owl:equivalentProperty, ?p2) | T(?x, ?p2, ?y) | |
| prp-eqp2 | 10 | T(?p1, owl:equivalentProperty, ?p2) | T(?x, ?p1, ?y) | |
| prp-pdw | 2 | T(?p1, owl:propertyDisjointWith, ?p2) | false | |
| prp-adp | 2 | T(?x, rdf:type, owl:AllDisjointProperties) | false | for each 1 ≤ i < j ≤ n |
| prp-inv1 | 10 | T(?p1, owl:inverseOf, ?p2) | T(?y, ?p2, ?x) | |
| prp-inv2 | 10 | T(?p1, owl:inverseOf, ?p2) | T(?y, ?p1, ?x) | |
| prp-key | | T(?c, owl:hasKey, ?u) | T(?x, owl:sameAs, ?y) | |
| prp-npa1 | 2 | T(?x, owl:sourceIndividual, ?i1) | false | |
| prp-npa2 | 2 | T(?x, owl:sourceIndividual, ?i) | false | |
| | notes | If | then | |
| cls-thing | 10 | | T(owl:Thing, rdf:type, owl:Class) | |
| cls-nothing1 | 10 | | T(owl:Nothing, rdf:type, owl:Class) | |
| cls-nothing2 | 2 | T(?x, rdf:type, owl:Nothing) | false | |
| cls-int1 | 11 class | T(?c, owl:intersectionOf, ?x) | T(?y, rdf:type, ?c) | |
| cls-int2 | 11 class | T(?c, owl:intersectionOf, ?x) | T(?y, rdf:type, ?c1) | |
| cls-uni | 11 class | T(?c, owl:unionOf, ?x) | T(?y, rdf:type, ?c) | for each 1 ≤ i ≤ n |
| cls-com | 2 | T(?c1, owl:complementOf, ?c2) | false | |
| cls-svf1 | 11 restriction & values-from | T(?x, owl:someValuesFrom, ?y) | T(?u, rdf:type, ?x) | |
| cls-svf2 | 11restriction & values-from | T(?x, owl:someValuesFrom, owl:Thing) | T(?u, rdf:type, ?x) | |
| cls-avf | 11 restriction & values-from | T(?x, owl:allValuesFrom, ?y) | T(?v, rdf:type, ?y) | |
| cls-hv1 | 11 restriction & values-from | T(?x, owl:hasValue, ?y) | T(?u, ?p, ?y) | |
| cls-hv2 | 11 restriction & values-from | T(?x, owl:hasValue, ?y) | T(?u, rdf:type, ?x) | |
| cls-maxc1 | 2 | T(?x, owl:maxCardinality, "0"^^xsd:nonNegativeInteger) | false | |
| cls-maxc2 | 11 restriction | T(?x, owl:maxCardinality, "1"^^xsd:nonNegativeInteger) | T(?y1, owl:sameAs, ?y2) | |
| cls-maxqc1 | 2 | T(?x, owl:maxQualifiedCardinality, "0"^^xsd:nonNegativeInteger) | false | |
| cls-maxqc2 | 2 | T(?x, owl:maxQualifiedCardinality, "0"^^xsd:nonNegativeInteger) | false | |
| cls-maxqc3 | 11 restriction | T(?x, owl:maxQualifiedCardinality, "1"^^xsd:nonNegativeInteger) | T(?y1, owl:sameAs, ?y2) | |
| cls-maxqc4 | 11 restriction | T(?x, owl:maxQualifiedCardinality, "1"^^xsd:nonNegativeInteger) | T(?y1, owl:sameAs, ?y2) | |
| cls-oo | | T(?c, owl:oneOf, ?x) | T(?y1, rdf:type, ?c) | |
| | | If | then | |
| cax-sco | 10 | T(?c1, rdfs:subClassOf, ?c2) | T(?x, rdf:type, ?c2) | |
| cax-eqc1 | 11 class | T(?c1, owl:equivalentClass, ?c2) | T(?x, rdf:type, ?c2) | |
| cax-eqc2 | 11 class | T(?c1, owl:equivalentClass, ?c2) | T(?x, rdf:type, ?c1) | |
| cax-dw | 2 | T(?c1, owl:disjointWith, ?c2) | false | |
| cax-adc | 2 | T(?x, rdf:type, owl:AllDisjointClasses) | false | for each 1 ≤ i < j ≤ n |
| | | If | then | |
| dt-type1 | | | T(dt, rdf:type, rdfs:Datatype) | for each datatype dt supported in OWL 2 RL |
| dt-type2 | 3 | | T(lt, rdf:type, dt) | for each literal lt and each datatype dt supported in OWL 2 RL |
| dt-eq | 3 | | T(lt1, owl:sameAs, lt2) | for all literals lt1 and lt2 with the same data value |
| dt-diff | 3 | | T(lt1, owl:differentFrom, lt2) | for all literals lt1 and lt2 with different data values |
| dt-not-type | 3 | T(lt, rdf:type, dt) | false | for each literal lt and each datatype dt supported in OWL 2 RL |
| | | If | then |
| scm-cls | 11 class | T(?c, rdf:type, owl:Class) | T(?c, rdfs:subClassOf, ?c) |
| scm-sco | 11 always | T(?c1, rdfs:subClassOf, ?c2) | T(?c1, rdfs:subClassOf, ?c3) |
| scm-eqc1 | 11 | T(?c1, owl:equivalentClass, ?c2) | T(?c1, rdfs:subClassOf, ?c2) |
| scm-eqc2 | 11 | T(?c1, rdfs:subClassOf, ?c2) | T(?c1, owl:equivalentClass, ?c2) |
| scm-op | | T(?p, rdf:type, owl:ObjectProperty) | T(?p, rdfs:subPropertyOf, ?p) |
| scm-dp | | T(?p, rdf:type, owl:DatatypeProperty) | T(?p, rdfs:subPropertyOf, ?p) |
| scm-spo | 10 | T(?p1, rdfs:subPropertyOf, ?p2) | T(?p1, rdfs:subPropertyOf, ?p3) |
| scm-eqp1 | | T(?p1, owl:equivalentProperty, ?p2) | T(?p1, rdfs:subPropertyOf, ?p2) |
| scm-eqp2 | | T(?p1, rdfs:subPropertyOf, ?p2) | T(?p1, owl:equivalentProperty, ?p2) |
| scm-dom1 | 11 | T(?p, rdfs:domain, ?c1) | T(?p, rdfs:domain, ?c2) |
| scm-dom2 | 11 | T(?p2, rdfs:domain, ?c) | T(?p1, rdfs:domain, ?c) |
| scm-rng1 | 11 | T(?p, rdfs:range, ?c1) | T(?p, rdfs:range, ?c2) |
| scm-rng2 | 11 | T(?p2, rdfs:range, ?c) | T(?p1, rdfs:range, ?c) |
| scm-hv | 11 | T(?c1, owl:hasValue, ?i) | T(?c1, rdfs:subClassOf, ?c2) |
| scm-svf1 | 11 | T(?c1, owl:someValuesFrom, ?y1) | T(?c1, rdfs:subClassOf, ?c2) |
| scm-svf2 | 11 | T(?c1, owl:someValuesFrom, ?y) | T(?c1, rdfs:subClassOf, ?c2) |
| scm-avf1 | 11 | T(?c1, owl:allValuesFrom, ?y1) | T(?c1, rdfs:subClassOf, ?c2) |
| scm-avf2 | 11 | T(?c1, owl:allValuesFrom, ?y) | T(?c2, rdfs:subClassOf, ?c1) |
| scm-int | | T(?c, owl:intersectionOf, ?x) | T(?c, rdfs:subClassOf, ?c1) |
| scm-uni | | T(?c, owl:unionOf, ?x) | T(?c1, rdfs:subClassOf, ?c) |