我想用PL-Unit
我想“断言”我在测试中指定的解决方案是 谓词的唯一 解决方案。
我不关心订单,在测试中指定了每个解决方案。
SWI-Prolog手册有一个很棒的部分叫testing non-deterministic predicates ...
2.2.3测试非确定性谓词
非确定性谓词成功为零次或多次。他们的结果使用findall / 3或setof / 3进行测试,然后进行值检查或使用all或set选项。以下是等效测试:
test(member) :-
findall(X, member(X, [a,b,c]), Xs),
Xs == [a,b,c].
test(member, all(X == [a,b,c])) :-
member(X, [a,b,c]).
这几乎是完全我需要的东西。但是,要传递这些测试,必须以正确的顺序指定输出:[a, b, c]
。我希望能够在任何顺序中指定它并仍然有测试通过。
假设我正在测试这个(假设的)谓词,它有两个解决方案。
specialNumber(X) :-
X is 2;
X is 4.
我可以像这样编写一个通过单元测试......
% PASSES!
test(specialNumber, all(X == [2, 4])) :-
specialNumber(X).
但如果我交换了解决方案的顺序,它就会失败......
% FAILS!
test(specialNumber, all(X == [4, 2])) :-
specialNumber(X).
无论找到解决方案的顺序如何,我如何进行此测试?
答案 0 :(得分:1)
考虑使用 setof/3
代替findall/3
来收集排序。
例如,考虑到谓词的略微重写定义:
special_number(X) :- ( X #= 2 ; X #= 4 ).
我们可以定义以下PlUnit测试:
:- begin_tests(all). test(solutions, Solutions = [2,4]) :- setof(X, special_number(X), Solutions). :- end_tests(all).
如果您重写您的谓词,继续,
special_number(X) :- ( X #= 4 ; X #= 2 ).
在这种情况下,我们有:
?- findall(X, special_number(X), Ls). Ls = [4, 2]. ?- setof(X, special_number(X), Ls). Ls = [2, 4].
作为setof/3
的替代方案,您可以使用:
findall/3
sort/2
手动对解决方案进行排序。您可以阅读相关主题:
bagof/3
(@<)/2
我将添加必要的库和指令作为练习运行上面的示例。