Make Prolog return one solution and stop showing the query option
Asked Answered
N

2

6

I'm new to prolog, and am experimenting with how to get it to stop querying after it finds one answer. I'm using this code:

member1(L,[L|_]).                    
member1(L,[_|RS]) :- member1(L,RS),!.      

The result is:

| ?- member1(3,[3,2,3]).

true ? a

yes

I'm lost as to how I could get Prolog to stop printing "true ?" and just print "yes" instead. I've tried using if/else construct and the format function but it still prints "true ?". Any ideas?

Nowadays answered 24/11, 2013 at 20:7 Comment(2)
You just want one answer? one true ? Τrue means that 3 is a member of the list [3,2,3]. The second true is that the query found it again in the list. ` member1(2,[3,2,3]).` would give you only one true.Dendritic
If you press enter after the first true (instead of ;), it would stop backtrackingDendritic
A
4

You're cutting the wrong place. Cut after the base condition, which says, "once the base is met, don't backtrack any more":

member1(L,[L|_]) :- !.                   
member1(L,[_|RS]) :- member1(L,RS).    

If-then does work for me, perhaps you implemented it different? (on swi-prolog)

member1(X,[Y|RS]) :-
    ( X = Y         -> true
    ; member1(X,RS) -> true
    ; false
    ) .

Swi also has the predicate once/1.

edited to account for the error pointed out by false.

Adanadana answered 24/11, 2013 at 22:1 Comment(1)
@false Ah! I had overlooked obvious situation in which the very first element matches. Fixed now. Thanks for pointing that out.Adanadana
I
2

From the output you show, I assume you are using GNU Prolog. But, first just an important remark:

The cut you placed does not cut as you intend it! In fact, it does not even prevent that there is a single answer. Here is evidence for that:

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

X = 1 ? ;

X = 2

yes

So you still have two answers. As a rule of thumb: a cut after a recursive goal often does some unexpected things.

If you insist to have exactly the first answer, simply say once(member(X,[1,2,3])). The once/1 is effectively a cut, too, but quite in disguise. It is tamed to do exactly one thing. Yes, you can place also cuts into recursive rules, but for a beginner, better leave that to a later lesson.

Behind all this there is another point, which is less visible: The toplevel shell of GNU Prolog will ask you for further solutions if it sees an open alternative (jargon: choicepoint). So when GNU asks you for more, it knows that some part has yet to be explored, but there is no guarantee, that there is actually another answer:

?- member(1-X,[1-a,2-b,3-c]). 

X = a ? ;

no

Here, the toplevel sees an open choicepoint and thus asks if you want to explore the query any further. Alas, this search is in vein...

Ical answered 25/11, 2013 at 1:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.