eyeprolog

Web names

Can web identifiers be ordinary Prolog atoms?

On the web, people, organizations, and projects are named by IRIs, global identifiers such as https://schema.org/name. This example stores a tiny knowledge graph whose names are IRIs written as quoted atoms, and joins facts across it with plain Prolog rules.

Run it in the playground · Source


The question

Which organizations is a person affiliated with, counting parent organizations? Who is the contact person for a project, and what is their email?

Because IRIs are globally unique, two facts that use the same IRI are about the same thing, wherever they came from. That makes joining data from different sources safe.


The facts

triple('<https://data.ugent.be/id/josd>', '<https://schema.org/affiliation>', '<https://data.ugent.be/id/idlab>').
triple('<https://data.ugent.be/id/idlab>', '<https://schema.org/parentOrganization>', '<https://data.ugent.be/id/ugent>').
triple('<https://github.com/eyereasoner/eyeprolog>', '<https://schema.org/maintainer>', '<https://data.ugent.be/id/josd>').

Each fact is a triple, subject–predicate–object, the shape of RDF data. The angle-bracketed IRIs are just quoted atoms; no prefix declarations are needed.


The rules

parent_organization(Unit, Org) :-
    triple(Unit, '<https://schema.org/parentOrganization>', Org).
parent_organization(Unit, Org) :-
    triple(Unit, '<https://schema.org/parentOrganization>', Mid),
    parent_organization(Mid, Org).

affiliated_with(Person, Org) :-
    triple(Person, '<https://schema.org/affiliation>', Unit),
    parent_organization(Unit, Org).

Affiliation is inherited up the organization tree, following parentOrganization links recursively. A second affiliated_with/2 clause covers the direct affiliation.


The answer

eyeprolog examples/web-names.pl
affiliated_with('<https://data.ugent.be/id/josd>', '<https://data.ugent.be/id/idlab>').
affiliated_with('<https://data.ugent.be/id/josd>', '<https://data.ugent.be/id/ugent>').
project_contact('<https://github.com/eyereasoner/eyeprolog>', '<https://data.ugent.be/id/josd>', "josderoo@gmail.com").

The person is affiliated with IDLab directly and with Ghent University through IDLab. The project contact comes from joining the maintainer triple with the email triple on the same IRI.


The reason

step(affiliated_with('<https://data.ugent.be/id/josd>', '<https://data.ugent.be/id/ugent>'),
     rule(11),
     ['Person' = '<https://data.ugent.be/id/josd>',
      'Org' = '<https://data.ugent.be/id/ugent>',
      'Unit' = '<https://data.ugent.be/id/idlab>'],

The UGent affiliation holds by the inherited-affiliation rule (clause 11) with IDLab as the intermediate unit. The step goes on to cite the affiliation triple and the parent-organization link.


The check

condition('C1', resolution, ok, 8).
condition('C4', coverage, ok, 9).
condition('C7', relevance, ok, 11).
verdict(checked).

All 8 steps are rule or fact steps, and the checker replays each one against the triples and rules. No built-in and no boundary is involved.


Try it

Learn more in The Art of EyeProlog, Chapter 15.