User-defined Rule Reasoning
This page discusses user-defined rule reasoning in Stardog.
Page Contents
Overview
Many reasoning problems may be solved with OWL’s axiom-based approach; but, of course, not all reasoning problems are amenable to this approach. A user-defined rules approach complements the OWL axiom-based approach nicely and increases the expressive power of a reasoning system from the user’s point of view. Many RDF databases support user-defined rules only. Stardog is the only RDF database that comprehensively supports both axioms and rules. Some problems (and some people) are simply a better fit for a rules-based approach to modeling and reasoning than to an axioms-based approach (and, of course, vice versa).
There isn’t a one-size-fits-all answer to the question “rules or axioms or both?” Use the thing that makes the most sense given the task at hand.
Stardog supports user-defined rule reasoning together with a rich set of built-in functions using the SWRL syntax and builtins library. In order to apply SWRL user-defined rules, you must include the rules as part of the database’s schema: that is, put your rules where your axioms are, i.e., in the schema. Once the rules are part of the schema, they will be used for reasoning automatically when using the SL reasoning type.
Assertions implied by the rules will not be materialized. Instead, rules are used to expand queries just as regular axioms are used.
To trigger rules to fire, execute a relevant query - simple and easy as the truth.
Stardog Rules Syntax
Stardog supports two different syntaxes for defining rules. The first is native Stardog Rules syntax and is based on SPARQL, so you can re-use what you already know about SPARQL to write rules. Unless you have specific requirements otherwise, you should use this syntax for user-defined rules in Stardog. The second is the de facto standard RDF/XML syntax for SWRL. It has the advantage of being supported in many tools; but it’s not fun to read or to write. You probably don’t want to use it. Better: don’t use this syntax!
Stardog Rules Syntax is basically SPARQL “basic graph patterns” (BGPs) plus some very explicit new bits (IF-THEN
) to denote the head and the body of a rule. Quick refresher: the IF
clause defines the conditions to match in the data; if they match, then the contents of the THEN
clause “fire”, that is, they are inferred and, thus, available for other queries, rules, or axioms, etc.
You define URI prefixes in the normal way (examples below) and use regular SPARQL variables for rule variables. As you can see, some SPARQL 1.1 syntactic sugar–property paths, especially, but also bnode syntax–make complex Stardog Rules concise and elegant.
It’s legal to use any valid Stardog function in Stardog Rules (see rule limitations below for few exceptions).
How to Use Stardog Rules
There are two things to sort out:
- Where to put these rules?
- How to represent these rules?
First, the rules go into the database, of course. Unless you’ve changed the value of reasoning.schema.graphs
database configuration option, you can store the rules in any named graph (or the default graph) in the database and you will be fine; that is, just add the rules to the database and it will all work out. Of course if you’ve tweaked reasoning.schema.graphs
, then you should put the rules into the named graph(s) that are specified in that configuration parameter.
You include the rules directly in a Turtle file loaded into Stardog. Rules can be mixed with triples in the file. Here’s an example:
:r a :Rectangle ;
:width 5 ;
:height 8 .
IF {
?r a :Rectangle ;
:width ?w ;
:height ?h
BIND (?w * ?h AS ?area)
}
THEN {
?r :area ?area
}
Rule Representation Options
Inline rules in Turtle data can be named for later reference and management. We assign an IRI, :FatherRule
in this example, to the rule and use it as the subject of other triples:
@prefix : <http://example.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
RULE :FatherRule
IF {
?x a <http://example.org/Male> , <http://example.org/Parent> .
}
THEN {
?x a <http://example.org/Father> .
}
:FatherRule rdfs:comment "This rule defines fathers" ;
a :MyRule .
In addition to the inline Turtle representation of rules, you can represent the rules with specially constructed RDF triples. This is useful for maintaining Turtle compatibility or for use with SPARQL INSERT DATA
. This example shows the object of a triple which contains one rule in Stardog Rules syntax embedded as literal.
@prefix rule: <tag:stardog:api:rule:> .
[] a rule:SPARQLRule;
rule:content """
IF {
?r a :Rectangle ;
:width ?w ;
:height ?h
BIND (?w * ?h AS ?area)
}
THEN {
?r :area ?area
}
""".
Rule Limitations & Gotchas
-
The RDF serialization of rules in, say, a Turtle file has to use the
tag:stardog:api:rule:
namespace URI and then whatever prefix, if any, mechanism that’s valid for that serialization. In the examples here, we use Turtle. Hence, we use@prefix
, etc.However, the namespace URIs used by the literal embedded rules can be defined in two places: the string that contains the rule–in the example above, you can see the default namespace is
urn:test:
–or in the Stardog database in which the rules are stored. Either place will work; if there are conflicts, the “closest definition wins”, that is, iffoo:Example
is defined in both the rule content and in the Stardog database, the definition in the rule content is the one that Stardog will use. -
Stardog Rule Syntax has the same expressivity of SWRL which means the SPARQL features allowed in rules are limited. Specifically, a triple pattern in a rule should be in one of the following forms:
- term1
rdf:type
class-uri - term1 prop-uri term2
where class-uri is a URI referring to a user-defined class and prop-uri is a URI referring to a user-defined property. Built-in URIs such as
rdfs:subClassOf
orowl:TransitiveProperty
are not allowed in rules.Only type of property paths allowed in rules are inverse paths (
^p
), sequence paths (p1 / p2
) and alternative paths (p1 | p2
) but these paths should not violate the above conditions. For example, the property pathrdf:type/rdfs:label
is not valid because according to the SPARQL spec this would mean the object of ardf:type
triple pattern is a variable and not a user-defined class.Rule body (
IF
) and only rule body may optionally containUNION
,BIND
orFILTER
clauses. However, functionsEXISTS
,NOT EXISTS
, orNOW()
cannot be used in rules. User-defined functions (UDF) may be used in rules but if the UDF is not a pure function then the results are undefined.Other SPARQL features are not allowed in rules.
- term1
-
Having the same predicate both in the rule body (
IF
) and the rule head (THEN
) are supported in a limited way. Cycles are allowed only if the rule body does not contain type triples or filters and the triples in the rule body are linear (i.e. no cycles in the rule body either).In other words, a property used in the rule head depends on a property in the rule body and this dependency graph may contain cycles under some limits. One of these is that a rule body should not contain type triples or filters. Tree-like dependencies are always allowed.
Of course the rule body may also contain triple patterns, which constitute a different kind of graph: it should be linear when edge directions are ignored. So no cycles or trees are allowed in this graph pattern. Linear when directions are ignored means that
{ ?x :p ?y . ?x :p ?z }
is linear but{ ?x :p ?y . ?x :p ?z . ?x :p ?t }
is not because there are three edges for the node represented by?x
.The reason for these limits boils down to the fact that recursive rules and axioms are rewritten as SPARQL property paths. This is why rule bodies cannot contain anything but property atoms. Cycles are allowed as long as we can express these as a regular grammar. Another way to think about this is that these rules should be as expressive as OWL property chains and the same restrictions defined for property chains
apply here, too.Let’s consider some examples. These rules are acceptable since no cycles appear in dependencies.
IF { ?x :hasFather ?y . ?y :hasBrother ?z } THEN { ?x :hasUncle ?z } IF { ?x :hasUncle ?y . ?y :hasWife ?z } THEN { ?x :hasAuntInLaw ?z }
These rules are not acceptable since there is a cycle:
IF { ?x :hasFather ?y . ?y :hasBrother ?z } THEN { ?x :hasUncle ?z } IF { ?x :hasChild ?y . ?y :hasUncle ?z } THEN { ?x :hasBrother ?z }
This kind of cycle is allowed:
IF { ?x :hasChild ?y . ?y :hasSibling ?z } THEN { ?x :hasChild ?z }
3 is a general limitation, not specific to Stardog Rules Syntax: recursion or cycles can occur through multiple rules, or it may occur as a result of interaction of rules with other axioms (or just through axioms alone).
Rules Examples
PREFIX rule: <tag:stardog:api:rule:>
PREFIX : <urn:test:>
PREFIX gr: <http://purl.org/goodrelations/v1#>
:Product1 gr:hasPriceSpecification [ gr:hasCurrencyValue 100.0 ] .
:Product2 gr:hasPriceSpecification [ gr:hasCurrencyValue 500.0 ] .
:Product3 gr:hasPriceSpecification [ gr:hasCurrencyValue 2000.0 ] .
IF {
?offering gr:hasPriceSpecification ?ps .
?ps gr:hasCurrencyValue ?price .
FILTER (?price >= 200.00).
}
THEN {
?offering a :ExpensiveProduct .
}
This example is self-contained: it contains some data (the :Product...
triples) and a rule. It also demonstrates the use of SPARQL’s FILTER
to do numerical (and other) comparisons.
Here’s a more complex example that includes four rules and, again, some data.
PREFIX rule: <tag:stardog:api:rule:>
PREFIX : <urn:test:>
:c a :Circle ;
:radius 10 .
:t a :Triangle ;
:base 4 ;
:height 10 .
:r a :Rectangle ;
:width 5 ;
:height 8 .
:s a :Rectangle ;
:width 10 ;
:height 10 .
IF {
?r a :Rectangle ;
:width ?w ;
:height ?h
BIND (?w * ?h AS ?area)
}
THEN {
?r :area ?area
}
IF {
?t a :Triangle ;
:base ?b ;
:height ?h
BIND (?b * ?h / 2 AS ?area)
}
THEN {
?t :area ?area
}
IF {
?c a :Circle ;
:radius ?r
BIND (math:pi() * math:pow(?r, 2) AS ?area)
}
THEN {
?c :area ?area
}
IF {
?r a :Rectangle ;
:width ?w ;
:height ?h
FILTER (?w = ?h)
}
THEN {
?r a :Square
}
This example also demonstrates how to use SPARQL’s BIND
to introduce intermediate variables and do calculations with or to them.
Let’s look at some other rules, but just the rule content this time for concision, to see some use of other SPARQL features.
This rule says that a person between 13 and 19 (inclusive) years of age is a teenager:
PREFIX swrlb: <http://www.w3.org/2003/11/swrlb#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
IF {
?x a :Person; :hasAge ?age.
FILTER (?age >= 13 && ?age <= 19)
}
THEN {
?x a :Teenager.
}
This rule says that a male person with a sibling who is the parent of a female is an “uncle with a niece”:
IF {
?x a :Person; a :Male; :hasSibling ?y;
?y :isParentOf ?z;
?z a :Female.
}
THEN {
?x a :UncleOfNiece.
}
We can use SPARQL 1.1 property paths (and bnodes for unnecessary variables (that is, ones that aren’t used in the THEN
) to render this rule even more concisely:
IF {
?x a :Person, :Male; :hasSibling/:isParentOf [a :Female]
}
THEN {
?x a :UncleOfNiece.
}
And of course a person who’s male and has a niece or nephew is an uncle of his niece(s) and nephew(s):
IF {
?x a :Male; :isSiblingOf/:isParentOf ?z
}
THEN {
?x :isUncleOf ?z.
}
A super user can read all of the things
IF {
?x a :SuperUser.
?y a :Resource.
?z a <http://www.w3.org/ns/sparql#UUID>.
}
THEN {
?z a :Role.
?x :hasRole ?z; :readPermission ?y.
}
Supported Built-Ins
Stardog supports a wide variety of functions from SPARQL, XPath, SWRL, and some native Stardog functions, too. All of them may be used in either Stardog Rules syntax or in SWRL syntax. The supported functions are enumerated SPARQL Query Functions.