Negation is difference

A negated atom removes rows. The eligible heirs from Part 2, dropping anyone with a criminal record:

eligible_heir(X) :- living_descendant(X), not criminal(X).

Both living_descendant and criminal are tables of names. Keeping the descendants who are not criminals is a set difference:

eligible_heir := living_descendant ∖ criminal
Difference needs its right-hand table complete before it runs. That is why negation must be stratified: finish criminal first, then subtract.