Search code examples
prologprolog-toplevel

Prolog Output Gives False After True


I have a prolog program to represent the flights between two states with their costs.

My program is this:

flight(newyork,washington,7). %its mean that there is a flight between both washington and newyork, newyork and washington with cost 7. 
flight(lasvegas,losangeles,4).
flight(california,arizona,8).

route(A,B,C):-
    flight(A,B,C);flight(B,A,C). %there is a route if there is a flight between A and B with cost C `OR` B and A with cost C.

Now, When I write a query like this:

?-route(washington,newyork,7).

its give me true. This query works good for me.

But when I write this query:

?-route(newyork,washington,7).

Its gives me firtsly true and after false.But I don't want this. I want only true,why it gives false after the true? Why it gives two outputs?


Solution

  • Its gives me firtsly true and after false. But I don't want this. I want only true, why it gives false after the true? Why it gives two outputs?

    Because Prolog has builtin backtracking. After it proposes a first solution, it will report that solution, but then it will backtrack in search for another solution.

    Depending on the exact query, Prolog can know in advance that there are no backtracking options. Prolog evaluates the facts/clauses of a predicate top-down, so that means that if it for example succeed with the last clause (and there are no recursive calls), it knows for sure that it has exhaustively searched all options.

    Here you write:

    route(A, B, C):-
        flight(A, B, C);
        flight(B, A, C).

    So that means if you call route(newyork, washington, 7)., it will first call flight(newyork, washington, 7).and that succeeds (it is even the first flight/3 fact), but there are still options how it could succeed: perhaps there is another flight(newyork, washington, 7) fact, so this could give true a second time.

    Most Prolog systems however have advanced lookup strategies to see that this is the only flight/3 fact with newyork as first parameter, so a modern Prolog system, will typically know in advance that there is no hope to find another flight/3 fact, but that does not mean we are done.

    You defined, in the body of your route/3 clause flight(B, A, C), so Prolog will start a search for flight/3, but with swapped locations. It will thus, after it has reported the first solution, continue the query, and call flight(washington, newyork, 7) in the hope to find another solution.

    If the query uses variables, this is quite useful, since in the proposed solutions, the the values that are assigned to the variables can (and very often are) different, so this can be used as a search tool.

    You can use the once/1 [swi-doc] meta-predicate to evaluate the call once. In that case either the predicate succeeds (and unifies variables), or it does not (and fails). Furthermore it is of course still possible that the predicate raises an error, or got stuck in an infinite loop.