質問

For homework, so nothing explicit, please:

Is there a way to get Prolog to return only the first Goal found by the program while ignoring the other Goals that are found?

For illustrative purposes, given the program:

permutation([X|Xs],Zs):-permutation(Xs,Ys), insert(X,Ys,Zs).
permutation([],[]).

Is there a way to make the program only return the first permutation as its only solution? In the following case:

| ?- permutation([1,2,3],X).

X = [1,2,3] ? ;

X = [1,3,2] ? ;

X = [2,1,3] ? ;

X = [2,3,1] ? ;

X = [3,1,2] ? ;

X = [3,2,1] ? ;

no

Can we just have

X = [1,2,3] ?;
no

as the solution?

役に立ちましたか?

解決

The cut it's the control you are looking for. Place it where you need to commit to a solution (here on toplevel, I guess). There is also the builtin once/1, that allows to restrict the scope of the commit 'locally' (useful for instance inside a conjunction inlined in a findall/3).

他のヒント

Prolog sets choicepoints whenever an alternative branch in the search tree is possible. In order to avoid backtracking to a choicepoint and exploring such alternatives, you have to add a cut (!/0).

You have to check where in your program the choicepoint is set, and add the cut after that call.

The best way to stick to the first solution is once/1 since this keeps the effects as local as possible. Using !/0 often has already unintended effects, since the scope of !/0 is larger. Let's take a very simple example: The query ( X = 1 ; X = 2 ; X = 3 ) in

p(X) :- ( X = 1 ; X = 2 ; X = 3 ).
p(4).

Using once/1 we get:

p1(X) :- once( ( X = 1 ; X = 2 ; X = 3 ) ).
p1(4).

?- p1(X).
X = 1 ;
X = 4.

Using !, we get only a single answer:

p2(X) :- ( X = 1 ; X = 2 ; X = 3 ), !.
p2(4).

?- p2(X).
X = 1.

Often this is not intended.

But there is a more general problem with committing to the first solution.

?- p1(2).
true.

?- dif(X,1),p1(X).
X = 2 ;
X = 4.

So, also 2 is now a first solution? It is for such reasons that committing must be used quite cautiously. A predicate that shows similar behavior as p1/1 lacks steadfastness. Such a predicate cannot be understood as a relation since it changes its meaning depending on the actual query.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top