Search code examples
prologtransitive-closurefailure-slicenon-termination

Why do i get a stack limit exceeded error when defining a predicate that convert the relation of two atoms?


I want to know why does the program goes in an infinite recursion in those cases:

?- love(kay, amanda).

and

?- love(rob, amanda).

And here is the code:

love(amanda, kay).
love(kay, geo).
love(geo, rob).

love(X, Y) :-
   love(X, Z),
   love(Z, Y).
love(X, Y) :-
   love(Y, X).

Solution

  • First, your program always goes into an infinite loop. No matter what names you are using. Even ?- loves(amanda, kay). loops. To better see this rather ask ?- loves(amanda, kay), false. Why am I so sure that your program always loops?

    To see this, we need some falsework. By adding goals false into your program, we get a new program requiring less (or equal) inferences.

    love(amanda, kay) :- false.
    love(kay, geo) :- false.
    love(geo, rob) :- false.
    love(X, Y) :-
       love(X, Z), false,
       love(Z, Y).
    love(X, Y) :-  false,
       love(Y, X).
    

    Because this fragment (called a ) does not terminate, your original program will not terminate. As you can see, all the persons have been removed. And thus actual names cannot influence the outcome.

    If you want to fix commutativity, rather introduce a further predicate:

    love2(X, Y) :- love1(X, Y).
    love2(X, Y) :- love1(Y, X).
    

    And to include the transitive closure, use closure/3:

    love3(X, Y) :-
       closure(love2, X, Y).