eyeprolog

RDF 1.2 named graphs

Can rules reason inside one graph without leaking into others?

A family graph says Alice is Bob’s parent and Bob is Carol’s. Rules derive ancestors, and every derived triple stays in the named graph its evidence came from.

Run it in the playground · Source


The question

Who is an ancestor of whom, according to the family graph?

This is one of a family of RDF 1.2 examples. RDF data arrives as rdf(Subject, Predicate, Object, Graph) facts, as produced by rdf-prolog-interchange. In a TriG dataset, the fourth argument names the graph that holds each triple.


The data

rdf(iri('https://example.org/alice'), iri('https://example.org/parent'), iri('https://example.org/bob'), iri('https://example.org/family')).
rdf(iri('https://example.org/bob'), iri('https://example.org/parent'), iri('https://example.org/carol'), iri('https://example.org/family')).

Both triples live in the named graph family. A named graph is a labelled set of triples, often one per source.


The rules

result_rdf(S, iri('https://example.org/ancestor'), O, G) :-
  rdf(S, iri('https://example.org/parent'), O, G).

result_rdf(S, iri('https://example.org/ancestor'), O, G) :-
  rdf(S, iri('https://example.org/parent'), M, G),
  rdf(M, iri('https://example.org/parent'), O, G).

A parent is an ancestor, and so is a parent’s parent. Because both goals share G, the two-step rule only joins parent links from the same graph.


The answer

eyeprolog examples/rdf12-trig-named-graph.pl
result_rdf(iri('https://example.org/alice'), iri('https://example.org/ancestor'), iri('https://example.org/bob'), iri('https://example.org/family')).
result_rdf(iri('https://example.org/bob'), iri('https://example.org/ancestor'), iri('https://example.org/carol'), iri('https://example.org/family')).
result_rdf(iri('https://example.org/alice'), iri('https://example.org/ancestor'), iri('https://example.org/carol'), iri('https://example.org/family')).

Two direct ancestors and one grandparent, all in family.


The reason

step(result_rdf(iri('https://example.org/alice'), iri('https://example.org/ancestor'), iri('https://example.org/bob'), iri('https://example.org/family')),
     rule(3),
     ['S' = iri('https://example.org/alice'),
      'O' = iri('https://example.org/bob'),
      'G' = iri('https://example.org/family')],
     [rdf(iri('https://example.org/alice'), iri('https://example.org/parent'), iri('https://example.org/bob'), iri('https://example.org/family'))]).

Alice is an ancestor of Bob by the first rule (clause 3), resting on one parent triple from the family graph.


The check

condition('C1', resolution, ok, 5).
condition('C4', coverage, ok, 7).
condition('C7', relevance, ok, 8).
trusted(0).
verdict(checked).

All five steps replay; nothing is trusted.


Try it

Learn more in The Art of EyeProlog, Chapter 4.