我为一些Prolog代码编写了一些测试,并获得了“使用choicepoint测试成功”的警告。这是我的一个测试:
test(overlap_intervals):-
overlap_intervals([0, 10], [5, 15]).
以下是代码:
%% precondition: X1<Y1 and X2<Y2
overlap_intervals([X1,Y1], [X2,Y2]):-
(X1<X2, Y1<Y2, Y1>X2); !,
(X1>X2, Y1>Y2, Y1<X2).
我从其他帖子中看到,我可以使用“nondet”test(foo, nondet) :- ....
来避免选择点,例如:
test(member, all(X == [a,b,c])) :-
member(X, [a,b,c]). % quoting Prolog document
但是,我正处理我的情况。 “nondet”将是一系列数字,而不是一个耗尽的列表。例如(显然不起作用,但实现了我的目标):
test(overlap_intervals, all(Y<10, Y>0)):-
overlap_intervals([0, 10], [Y, 15]).
有人可以解释为什么有选择点以及如何在我的情况下避免它们吗?
答案 0 :(得分:1)
有一个选择点,因为在混合;
和!
时,您对优先级感到困惑。像往常一样,和(,
)比或(;
)更强大。
编写谓词的更好方法是:
overlap_intervals_2([X1,Y1], [X2,Y2]):-
( (X1<X2, Y1<Y2, Y1>X2),
!
; (X1>X2, Y1>Y2, Y1<X2) ).
或(首选):
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).
这些替代定义使得切割所属的位置更加清晰,突出显示它在您的版本中放错位置。测试:
?- overlap_intervals([0, 10], [5, 15]).
true ;
false.
?- overlap_intervals_2([0, 10], [5, 15]).
true.
?- overlap_intervals_3([0, 10], [5, 15]).
true.
请注意,这些定义都不包括一个间隔包含在另一个间隔内的情况。我会说overlap_intervals([0, 10], [1, 9])
应该是正确的,但谓词的确切含义当然取决于你的应用。
至于您在测试头中使用all
,我认为all(between(0, 10, Y))
应该有效(未经测试)。