简体   繁体   中英

Prolog: 'cut' in query vs. rules/facts

Doing exercise 10.4 on learnprolognow , could someone explain to me or help me visualize why for ?- p(X),p(Y) we get:
X=1,Y=1; X=1,Y=2; X=2, Y=1; X=2, Y=1. And not just X=1, Y=1; X=1, Y=2. X=1, Y=1; X=1, Y=2.

I think I'm misunderstanding how the cut happens, when it's in the ruleset instead of the query - because I think I can visualize it for ?- p(X),!,p(Y). , where it actually behaves as I thought the last one would...

Edit: From the website

% database
p(1).
p(2):-!.
p(3).

% Queries
p(X). % returns: X=1; X=2.
p(X),p(Y). % returns: X=1,Y=1; X=1, Y=1; X=2, Y=2. (?)
p(X),!,p(Y). % returns X=1, Y=1; X=1, Y=2.

To understand this problem you can imagine a tree with X in as first level and Y as second level (prolog uses sld resolution that can be well described with a tree). Consider this problem:

p(1).
p(2):-!.
p(3).

sol(X,Y):-
    p(X),
    p(Y).

I've added the predicate solve/2 to make it more clear. Run the query:

?- solve(X,Y).

First of all you have to choose the value for X . Prolog uses depth first search from the top to the bottom, from left to right. So it evaluates p(x) : p(1) succeed (because is the first clause, if you write p(2) above p(1) , p(2) will succeed) and so X = 1 . Then evaluates p(Y) : p(1) succeed and so you have the first solution:

X = Y, Y = 1.

If you click on more, then prolog does a backtrack (you can imagine this as a step above on the tree) and tries another value for p(Y) . In this case p(2) succeed, the predicate is true and you get:

X = 1, Y = 2.

Now, if you click on more, due to the fact there is a cut ( ! ) in the body of p(2) (a general rule in prolog has the form head :- body ), prolog will not go more in depth and p(3) is ignored. So there's no more solution to p(Y) . So there is another backtracking and this time, for p(X) , p(2) succeed and X = 2 and for p(Y) , p(1) succeed and you get:

X = 2, Y = 1.

If you click on more, you get:

X = Y, Y = 2.

Now, due to the fact there is a cut after p(2) , there are no more solutions available for both X and Y ( ! cuts everything below p(2) ).

If you remove the cut you get all the possible solutions:

X = Y, Y = 1
X = 1,
Y = 2
X = 1,
Y = 3
X = 2,
Y = 1
X = Y, Y = 2
X = 2,
Y = 3
X = 3,
Y = 1
X = 3,
Y = 2
X = Y, Y = 3

Keep in mind that the order of the clauses is important. If you write

p(2).
p(1):-!.
p(3).

You get

X = Y, Y = 2
X = 2,
Y = 1
X = 1,
Y = 2
X = Y, Y = 1

You can check this behaviour using the tracer. In SWI or SWISH you can write ?- trace, solve(X,Y).

If you have a situation like this:

p(1).
p(2).
p(3).

sol(X,Y):-
    p(X),
    !,
    p(Y).

prolog will tests all the possible values for Y and only one value for X because the cut stops the exploration of the tree (ideally you have 3 branches for X (1,2,3) and 3 for Y (1,2,3), ! cuts 2 and 3 from X ) and you get:

X = Y, Y = 1
X = 1,
Y = 2
X = 1,
Y = 3

Sorry for the long post, hope to be clear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM