Search code examples
loopsprolog

Prolog falls into an infinite loop


Ι need to write each element once, for example, Belgium borders France, and it should automatically imply that France borders Belgium. Unfortunately, the statement borders(X, Y) :- borders(Y, X). falls into an infinite loop.

% Knowledge
borders('Belgium', 'France').
borders('Belgium', 'Germany').
borders('Belgium', 'Luxembourg').
borders('Belgium', 'Netherlands').
borders('Denmark', 'Germany').
borders('France', 'Germany').
borders('France', 'Luxembourg').
borders('Germany', 'Luxembourg').
borders('Germany', 'Netherlands').

% Rule
borders(X, Y) :- borders(Y, X).

It shows me all of the following

? - borders('France', X).
X = 'Germany' ;
X = 'Luxembourg' ;
X = 'Belgium' ;
X = 'Germany' ;
X = 'Luxembourg' ;
X = 'Belgium' ;
X = 'Germany' ;
X = 'Luxembourg' ;
X = 'Belgium' ;
X = 'Germany' ;
X = 'Luxembourg' ;
X = 'Belgium' ;
X = 'Germany' . 

while it should stop at borders

? - ('France', X).
X = 'Germany' ;
X = 'Luxembourg' ;
X = 'Belgium'

Solution

  • To avoid the infinite loop, due to the recursive definition, use distinct predicate names for rules and facts (for example, borders and border):

    borders(X, Y) :- border(X, Y).
    borders(X, Y) :- border(Y, X).
    
    border('Belgium', 'France').
    border('Belgium', 'Germany').
    border('Belgium', 'Luxembourg').
    border('Belgium', 'Netherlands').
    border('Denmark', 'Germany').
    border('France', 'Germany').
    border('France', 'Luxembourg').
    border('Germany', 'Luxembourg').
    border('Germany', 'Netherlands').
    

    Example:

    ?- borders('France', X).
    X = 'Germany' ;
    X = 'Luxembourg' ;
    X = 'Belgium'.
    

    EDIT

    The computation performed to answer a query can be represented as a tree. Prolog searches this tree using depth-first search, automatically backtracking when it encounters a failure node (or when the user presses the key ';' to get an alternate answer). During the search, clauses are used in the order they appear in the program. At the end of the search, Prolog displays false only if the last node visited in the tree is a failure node. So, to understand why Prolog behaves differently for different queries, you can compare the search trees that it explores in each of them:

    • Both rules of the predicate borders/2 produce solutions:

    enter image description here

    • Only the first rule of the predicate borders/2 produces a solution:

    enter image description here

    • Only the second rule of the predicate borders/2 produces solutions:

    enter image description here