Prolog: stop condition?

南笙酒味 提交于 2019-12-13 08:49:31

问题


Here's a very trivial Prolog knowledge base:

spouse(bill,cheryl).
married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).

I ran the following queries. Note that sometimes the answer is the correct name (only), but other times the answer is the correct name and "false".

1 ?- married(bill,X).
X = cheryl ;
false.

2 ?- married(cheryl,X).
X = bill.

3 ?- married(X,bill).
X = cheryl.

4 ?- married(X,cheryl).
X = bill ;
false.

Can someone explain this seemingly inconsistent behavior? Thanks in advance.


回答1:


The false response from Prolog means that Prolog had a choice point to go back to in an attempt to find further answers and it found no more. The order in which your predicates and facts are set up can impact whether it thinks it has more choices to explore.

In the given case:

spouse(bill,cheryl).

married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).

1 ?- married(bill,X).
X = cheryl ;
false.

2 ?- married(cheryl,X).
X = bill.

3 ?- married(X,bill).
X = cheryl.

4 ?- married(X,cheryl).
X = bill ;
false.

In the two false cases, the query married/2 is satisfied by the first of two married/2 clauses. Once satisified, Prolog realizes it has another choice to make (the second married/2 clause), and prompts for you to look for more. You press ;, then Prolog explores the second (and final) clause, finds no more solutions, and comes back false.

Swap the order of your married/2 clauses and see what happens:

spouse(bill,cheryl).

married(X,Y) :- spouse(Y,X).
married(X,Y) :- spouse(X,Y).

?- married(bill,X).
X = cheryl.

?- married(cheryl,X).
X = bill ;
false.

?- married(X,bill).
X = cheryl ;
false.

?- married(X,cheryl).
X = bill.

As expected, the results are reversed since we've changed which queries are satisfied by the first clause.

The false response can appear inconsistent to beginning Prolog programmers and "feel" like an error or warning, but it's actually a perfectly normal Prolog response. Prolog is quite consistent in its behavior of attempting to find solutions and, when no more choices exist, will return false. If Prolog has exhausted all the other choices before it finds the final solution, it displays the solution and doesn't return false (as in the case above in which the second clause is the only solution).

There is a temptation to try and "clean up" the false responses by using cuts. Although this can have the desired short-term result, it is risky since you are removing choice points from the predicate and as you add data and logic may eliminate solutions which you really want.

Thus, in the modified case:

spouse(bill,cheryl).
spouse(emma,nate).

married(X,Y) :- spouse(X,Y), !.  % If we found the spouse, we're done, no more!
married(X,Y) :- spouse(Y,X).

?- married(bill,X).
X = cheryl.

?- married(cheryl,X).
X = bill.

?- married(X,bill).
X = cheryl.

?- married(X, cheryl).
X = bill.

Yay, life is good! But wait, what if we do this:

?- married(X,Y).
X = bill,
Y = cheryl.

?-

Are bill and cheryl the only married couple? No... it left out nate and emma. The cut eliminated the rest of the solutions.



来源:https://stackoverflow.com/questions/21390786/prolog-stop-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!