Search code examples
prolog

unexpected prolog backtracking even in simple program


The following is a very simple prolog program.

parent(john, jane).
parent(john, james).
parent(sally, jane).

The following simple query results in prolog answering true, but also false after prompting for more answers.

?- parent(john, jane).
true ;
false.

Question: Why does prolog do this?

Swi-prolog, swish and gprolog all do this.

Thoughts

Prolog should be able to answer this question with simple unification, and exhaust the database of facts with no need to create a choice point. What is the "choice"?

My understanding is that choicepoints, for backtracking to, are created for variables that are not bound at query time. There are no variables here - none in the database of facts/rules, and none in the query.

A similar question (see below) resulted in comments suggesting indexing. I am no expert but that suggests a mechanism for prolog to internally store and search facts. Indexing resulting in a choice point feels like a failure in optimisation.

Similar Question

This question is a smaller, more focussed one, as a result of a previous question. The clarity resulting from the comments there merited this new question, to help focus the question and also help new readers.

unexpected backtracking in simple prolog example


Solution

  • My understanding is that choicepoints, for backtracking to, are created for variables that are not bound at query time.

    Choicepoints are created when the search tree branches and Prolog has to choose which branch to explore next. They are not tied to unbound variables, although they do affect variable binding, they are tied to the way it explores the search tree looking for answers.

    What is the "choice"?

    Despite the code being abstract "logical relations" it really works through your code line by line from top to bottom - your code representing a root of a tree which branches three times for three parent/2 predicates - and at the first branch it has found a valid answer to the query so it sets a choicepoint "I am here in the tree, and choosing this answer" and gives the answer to you.

    parent(john, jane).  <-- *choose* this valid answer, wait for your input.
    parent(john, james).
    parent(sally, jane).
    

    There are more branches, more parent/2 predicates not checked, there might be more results hiding in those parts of the tree and it needs to back up to the root and then proceed down into the next parent/2 branch to find out. It won't know until it looks, and it won't look until you ask it to. You could change the code to have two valid answers:

    parent(john, jane).
    parent(john, james).
    parent(john, jane).
    

    Then:

    ?- parent(john, jane).
    true ;
    true.
    

    what would you expect this version to do in your approach?

    NB. that the second true does not leave a choicepoint because all the parent/2 predicates have been checked by then.

    Prolog should be able to answer this question with simple unification, and exhaust the database of facts with no need to create a choice point.

    It can answer with simple unification. It doesn't search ahead of the current search point on the offchance that there might be no more answers, it's from the 1970s, that would be impossible for performance. Likely you could build a variant Prolog which did meet a choicepoint, spawn a second searcher to run ahead if the code falls below some simplicity cutoff point, wait for whether it finds more answers or runs out, before deciding whether to set a choicepoint - but then it wouldn't behave like Prolog behaves and ... what would be the benefit, what would you gain? As you say, you can already table predicates to reduce searching and improve performance in certain situations.