Reputation: 171
I wrote some tests for some Prolog codes and got "Test succeeded with choicepoint" warning. Here's one of my tests:
test(overlap_intervals):-
overlap_intervals([0, 10], [5, 15]).
Here's the codes:
%% precondition: X1<Y1 and X2<Y2
overlap_intervals([X1,Y1], [X2,Y2]):-
(X1<X2, Y1<Y2, Y1>X2); !,
(X1>X2, Y1>Y2, Y1<X2).
I saw from other posts that I can use "nondet" test(foo, nondet) :- ....
to avoid choice points, such as:
test(member, all(X == [a,b,c])) :-
member(X, [a,b,c]). % quoting Prolog document
However, I'm dealing with intervals in my case. The "nondet" would be a range of numbers, rather than an exhaustible list. For example (which apparently doesn't work but gets my goal across):
test(overlap_intervals, all(Y<10, Y>0)):-
overlap_intervals([0, 10], [Y, 15]).
Can someone explain why there are choicepoints and how to avoid them in my case?
Upvotes: 1
Views: 151
Reputation: 9378
There is a choicepoint because you got confused about precedence when mixing ;
and !
. As usual in logic, and (,
) binds stronger than or (;
).
Better ways of writing your predicate would be:
overlap_intervals_2([X1,Y1], [X2,Y2]):-
( (X1<X2, Y1<Y2, Y1>X2),
!
; (X1>X2, Y1>Y2, Y1<X2) ).
or (preferred):
overlap_intervals_3([X1,Y1], [X2,Y2]):-
(X1<X2, Y1<Y2, Y1>X2),
!.
overlap_intervals_3([X1,Y1], [X2,Y2]):-
(X1>X2, Y1>Y2, Y1<X2).
These alternative definitions make it clearer where the cut belongs, highlighting that it was misplaced in your version. Tests:
?- overlap_intervals([0, 10], [5, 15]).
true ;
false.
?- overlap_intervals_2([0, 10], [5, 15]).
true.
?- overlap_intervals_3([0, 10], [5, 15]).
true.
Note that none of these definitions cover the case where one interval is contained within another one. I would say that overlap_intervals([0, 10], [1, 9])
should be true, but the exact meaning of the predicate depends on your application, of course.
As for your use of all
in a test head, all(between(0, 10, Y))
should work, I think (not tested).
Upvotes: 1