The Wikipedia section on this topic is a mess. It states:
Pure Prolog is based on a subset of first-order predicate logic, Horn clauses, which is Turing-complete. Turing completeness of Prolog can be shown by using it to simulate a Turing machine:
(emphasis added)
And then it goes on to show code that uses things that are not Horn clauses (!
and once
):
turing(Tape0, Tape) :-
perform(q0, [], Ls, Tape0, Rs),
reverse(Ls, Ls1),
append(Ls1, Rs, Tape).
perform(qf, Ls, Ls, Rs, Rs) :- !.
perform(Q0, Ls0, Ls, Rs0, Rs) :-
symbol(Rs0, Sym, RsRest),
once(rule(Q0, Sym, Q1, NewSym, Action)),
action(Action, Ls0, Ls1, [NewSym|RsRest], Rs1),
perform(Q1, Ls1, Ls, Rs1, Rs).
symbol([], b, []).
symbol([Sym|Rs], Sym, Rs).
action(left, Ls0, Ls, Rs0, Rs) :- left(Ls0, Ls, Rs0, Rs).
action(stay, Ls, Ls, Rs, Rs).
action(right, Ls0, [Sym|Ls0], [Sym|Rs], Rs).
left([], [], Rs0, [b|Rs0]).
left([L|Ls], Ls, Rs, [L|Rs]).
rule(q0, 1, q0, 1, right).
rule(q0, b, qf, 1, stay).
OK, so Prolog is Turing-complete. No one doubted that. What about pure Prolog?
If pure Prolog is, in fact, Turing-complete, how come we seemingly can't implement list intersection (the first list filtered by membership in the second list) in it? All implementations use at least one of the following: !
, \+
, findall
, call
directly or indirectly.
!
andonce
would be pure and correct. With a nondeterministic Turing machine, the code without!
andonce
would be pure and more correct than now since it would explore all possible executions. This shows that pure Prolog is Turing complete, both for deterministic and nondeterministic machines. – Isabelle Newbierandom_between(1,N,Choice)
for theN
next possible clauses, then cutting. No going back. – David TonhoferN
Everettian universes (and in each universe, it commits) in order to be able to accept a problem in NP in polynomial time... – David Tonhofer