Skip to content

Rule syntax by examples

Maximilian Marx edited this page Mar 2, 2020 · 3 revisions

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, and recentDeathsCause of arity two.
  • The parameters of sparql function are: (1) the url of the sparql endpoint, the variable names in the SELECT clause, and the graph pattern in the WHERE 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.
Clone this wiki locally