# Goal determinism when less than 2 solutions

It seems common to have a predicate that produces one solution, leaving behind some choicepoints to check which then never result in a second solution, thus producing an unwanted “there may be more solutions… oh there isn’t” teaser.

These wrappers should help reduce that, with the disadvantage that the Goal is called twice.

``````% For predicates intended to never succeed twice
succeeds_once(Goal) :-
% Ensure there are not 2 solutions or more
\+ call_nth(Goal, 2),
Goal,
!.

% For predicates which can have many solutions, but usually 1
fewer_choicepoints(Goal) :-
(   \+ call_nth(Goal, 2)
% Less than 2 solutions, so cut after it
->  Goal, !
;   Goal
).
``````

These will reduce unwanted choicepoints, when there is 1 solution, whilst being convenient to use:

``````?- member(X, [a]) ; false.
X = a ;
false. % An example of an unwanted choicepoint

?- succeeds_once(member(X, [a]) ; false).
X = a. % No unwanted choicepoint

?- succeeds_once(member(X, [a]) ; true).
false. % Bypasses presenting the first solution of the 2 solutions

?- fewer_choicepoints(member(X, [a]) ; false).
X = a. % No unwanted choicepoint

?- fewer_choicepoints(member(X, [a, b]) ; false).
X = a ;
X = b ;
false. % Redundant choicepoint - no worse than usual
``````

Perhaps there are better, succinct names for these predicates.

1 Like

A request for a solution set could apply here. How about findall/3? It returns only one answer.

``````  ?- findall(X, member(X,[a]),All).
All = [a].

?- findall(X, member(X,[]),All).
All = [].

?- findall(X, member(X,[a,b,c]),All).
All = [a, b, c].
``````

Dealing with just `Goal`, rather than having to also manually identify the variables involved, is more convenient.

A list of variables can be more difficult to visually digest, depending on their complexity (e.g. compound terms), especially if some of the variable components are themselves lists.

1 Like