-
Notifications
You must be signed in to change notification settings - Fork 13
Rule syntax by examples
In this page we describe the rule syntax implemented in Rulewerk in six examples that conform our Doid Example, presented in VLog: A Rule Engine for Knowledge Graphs.
See also:
Example 1. @prefix
declarations.
We can use @base
and @prefix
declarations in order to simplify rules and source declarations.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix wdqs: <https://query.wikidata.org/> .
Please note:
-
@base
can be used once at the beginning of the file -
@prefix
can be used after@base
if defined - Prefix declarations, as
@source
declarations, and rules (including facts) end with a dot. This allows us to write rules in multiple lines.
Example 2. @source
declarations
VLog and Rulewerk can integrate multiple data sources. This is done in Rulewerk through @source
declarations
@source doidTriple[3]: load-rdf("src/main/data/input/doid.nt.gz") .
@source diseaseId[2]: sparql(wdqs:sparql, "disease,doid", "?disease wdt:P699 ?doid .") .
@source recentDeaths[1]: sparql(wdqs:sparql, "human",
'''?human wdt:P31 wd:Q5;
wdt:P570 ?deathDate .
FILTER (YEAR(?deathDate) = 2018)''') .
@source recentDeathsCause[2]: sparql(wdqs:sparql, "human,causeOfDeath",
'''?human wdt:P31 wd:Q5;
wdt:P570 ?deathDate ;
wdt:P509 ?causeOfDeath .
FILTER (YEAR(?deathDate) = 2018)''') .
Please note:
- With the first source declaration Vlog loads a local RDF file into VLog, and associate its content to a predicate named
doidTriple
with arity 3. - With the second, third, and fourth source declarations Vlog executes a SPARQL query on Wikidata endpoint and associate the data to the predicate names
diseaseId
of arity two,recentDeaths
of arity one, andrecentDeathsCause
of arity two. - The parameters of
sparql
function are: (1) the url of the sparql endpoint, the variable names in theSELECT
clause, and the graph pattern in theWHERE
clause in the sparql query. - The first
@source
declaration is equivalent to:SELECT ?disease ?doid WHERE { ?disease wdt:P699 ?doid. }
- We use the prefix
wdqs
defined in Example 1.
Example 3. Variables and Comments. Rulewerk rule syntax differentiate universally from existentially quantified variables.
% Combine recent death data (infer "unknown" cause if no cause given):
deathCause(?X, ?Z) :- recentDeathsCause(?X, ?Z) .
deathCause(?X, !Z) :- recentDeaths(?X) .
% Mark Wikidata diseases that have a DOID:
hasDoid(?X) :- diseaseId(?X, ?DoidId) .
- Lines starting with an
%
are interpreted as comments. - Empty lines, spaces, and tabs are ignored.
- Universally quantified variables are prefixed with a question mark
?
. - Existentially quantified variables are prefixed with an exclamation mark
!
. - It is not important if a variable name starts with an uppercase letter anymore.
- We believe that these variable prefixes facilitate the process of writing rules.
- It also enables the detection of syntax errors at parsing time.
Example 4. IRIs. Rulewerk rule syntax support IRIs as both: predicate names and constants
% Relate DOID string ID (used on Wikidata) to DOID IRI (used in DOID ontology)
doid(?Iri, ?DoidId) :- doidTriple(?Iri, <http://www.geneontology.org/formats/oboInOwl#id>,?DoidId) .
% Compute transitive closure of DOID subclass hierarchy
diseaseHierarchy(?X, ?Y) :- doidTriple(?X, rdfs:subClassOf, ?Y) .
diseaseHierarchy(?X, ?Z) :- diseaseHierarchy(?X, ?Y), doidTriple(?Y, rdfs:subClassOf, ?Z) .
Please note:
- The first rule usea full IRI
<http://www.geneontology.org/formats/oboInOwl#id>
as a constant. - Second and third rules uses a prefixed IRI (
rdfs:subClassOf
) instead.
Example 5. RDF Literals. Rulewerk rule syntax supports string literals, i.e. single and triple quoted and sigle-quoted strings.
cancerDisease(?Xdoid) :- diseaseHierarchy(?X, ?Y), doid(?Y, "DOID:162"), doid(?X, ?Xdoid) .
Please note:
- RDF Literals are automatically transformed into their canonical form.
- All the following RDF Literal are equivalent
"DOID:162"
'DOID:162'
"""DOID:162"""
'''DOID:162'''
Example 6. Stratified negation
% Compute who died of cancer and who died of something else (including diseases unknown to DOID):
humansWhoDiedOfCancer(?X) :- deathCause(?X, ?Y), diseaseId(?Y, ?Z), cancerDisease(?Z) .
humansWhoDiedOfNoncancer(?X) :- deathCause(?X, ?Y), diseaseId(?Y, ?Z), ~cancerDisease(?Z) .
humansWhoDiedOfNoncancer(?X) :- deathCause(?X, ?Y), ~hasDoid(?Y) .
Please note:
- We use the prefix
~
to indicate that a Literal is negated. - All variables in negated literals have to be bound. If a variable can not be bound, then VLog and Rulewerk throw an exception.