Saying that something exists, without knowing what it is, and without mixing it up with anything else.
existential-rules.py · output · proof · check · try it in the playground
Some rules conclude that something exists without saying what it is:
How can a reasoner keep track of such unknowns without confusing one with another, or with anything it already knows?
A variable that appears in a rule’s conclusion but not in its body is such an unknown, an existential:
implies(person(X), has_parent(X, P)) # P: some parent of X
implies(ordered(C, Item), invoice_for(C, I)) # I: some invoice for C
implies(colleagues(X, Y), meeting(M) & attends(M, X) & attends(M, Y))
Around them: Ann and Bob are persons, Dan and Fay have a parent the data names (Eve), Carl ordered a lamp and a desk, Dora a chair, and Ann and Dora are colleagues.
has_parent('ann', '…/genid/examples#sk_0')
has_parent('bob', '…/genid/examples#sk_1')
sibling('dan', 'fay')
sibling('fay', 'dan')
invoice_for('carl', '…/genid/examples#sk_2')
invoice_for('dora', '…/genid/examples#sk_3')
sent('…/genid/examples#sk_2')
sent('…/genid/examples#sk_3')
meeting('…/genid/examples#sk_4')
attends('…/genid/examples#sk_4', 'ann')
attends('…/genid/examples#sk_4', 'dora')
Each unknown became a Skolem atom, here shortened: a name that stands for
“the one that exists here”. The full name starts with
https://eyereasoner.github.io/.well-known/genid/.
sk_0 and sk_1. Had they
shared one, the sibling rule would have made them siblings by accident.
Only Dan and Fay, whose parent the data names, are siblings.sk_4.sent rule uses the invoices like any
other value. Whenever a rule meets the same activation again, it gives back
the same witness, so reasoning comes to an end.The witnesses live in a namespace of their own, with a genid that is a random identifier for each run, as EYE does. So a witness never clashes:
'sk_0';The saved files use the genid examples, so they can be reproduced:
--skolem-genid examples does the same on the command line.
For Bob’s parent:
sk_1 — clause 3, with X = bob and P =
that witness.For Carl’s invoice: Carl ordered a lamp (clause 7), so he has the invoice
sk_2 (clause 10). The desk is not needed: it would only give the same
conclusion again, and peye --unused says so.
The checker confirms every step against the program: 18 steps are instances
of the clauses they cite, and the two not_identical tests are recomputed.
Nothing is taken on trust. Verdict: checked.
The witnesses need no special treatment in the proof: they are ordinary values that the rule’s variables were bound to.
python -m peye examples/existential-rules.py # a fresh genid each run
python -m peye --skolem-genid examples examples/existential-rules.py # the saved output
python -m peye --proof examples/existential-rules.py # with the proof
Or open it in the playground.
Add fact(person('dan')) and run again: Dan gets a parent witness of his own
as well, beside Eve, because the rule says only that some parent exists.
An existential rule says that something exists. peye gives each such something a name of its own, keeps it when the same activation returns, and makes sure it can never be mistaken for anything else.