Reading a cut ! in Prolog

2019-06-24 00:40发布

问题:

I am reading through Learn Prolog Now! 's chapter on cuts and at the same time Bratko's Prolog Programming for Artificial Intelligence, Chapter 5: Controlling Backtracking. At first it seemed that a cut was a straight-forward way to mimic an if-else clause known from other programming languages, e.g.

# Find the largest number
max(X,Y,Y):- X =< Y,!. 
max(X,Y,X).

However, as is noted down the line this code will fail in cases where all variables are instantiated even when we expect false, e.g.

?- max(2,3,2).
true.

The reason is clear: the first rule fails, the second does not have any conditions connected to it anymore, so it will succeed. I understand that, but then a solution is proposed (here's a swish):

max(X,Y,Z):- X =< Y,!, Y = Z. 
max(X,Y,X).

And I'm confused how I should read this. I thought ! meant: 'if everything that comes before this ! is true, stop termination including any other rules with the same predicate'. That can't be right, though, because that would mean that the instantiation of Y = Z only happens in case of failure, which would be useless for that rule.

So how should a cut be read in a 'human' way? And, as an extension, how should I read the proposed solution for max/3 above?

回答1:

See also this answer and this question.

how should I read the proposed solution for max/3 above?

max(X,Y,Z):- X =< Y, !, Y = Z. 
max(X,Y,X).

You can read this as follows:

When X =< Y, forget the second clause of the predicate, and unify Y and Z.

The cut throws away choice points. Choice points are marks in the proof tree that tell Prolog where to resume the search for more solutions after finding a solution. So the cut cuts away parts of the proof tree. The first link above (here it is again) discusses cuts in some detail, but big part of that answer is just citing what others have said about cuts elsewhere.

I guess the take home message is that once you put a cut in a Prolog program, you force yourself to read it operationally instead of declaratively. In order to understand which parts of the proof tree will be cut away, you (the programmer) have to go through the motions, consider the order of the clauses, consider which subgoals can create choice points, consider which solutions are lost. You need to build the proof tree (instead of letting Prolog do it).

There are many techniques you can use to avoid creating choice points you know you don't need. This however is a bit of a large topic. You should read the available material and ask specific questions.