gpt4 book ai didi

unit-testing - 什么是 PL-Unit 中的 "Test succeeded with choicepoint"警告,我该如何解决?

转载 作者:行者123 更新时间:2023-12-04 16:51:12 27 4
gpt4 key购买 nike

我正在写一个序言程序到 检查变量是否为整数 .
我“返回”结果的方式很奇怪,但我认为这对回答我的问题并不重要。

测试

我已经为这种行为编写了通过单元测试;他们来了...

foo_test.pl

:- begin_tests('foo').
:- consult('foo').

test('that_1_is_recognised_as_int') :-
count_ints(1, 1).

test('that_atom_is_not_recognised_as_int') :-
count_ints(arbitrary, 0).

:- end_tests('foo').
:- run_tests.

编码

这是通过这些测试的代码......

文件名
count_ints(X, Answer) :-
integer(X),
Answer is 1.

count_ints(X, Answer) :-
\+ integer(X),
Answer is 0.

输出

测试通过了,这很好,但我是 收到警告 当我运行它们时。这是运行测试时的输出...
?- ['foo_test'].
% foo compiled into plunit_foo 0.00 sec, 3 clauses
% PL-Unit: foo
Warning: /home/brandon/projects/sillybin/prolog/foo_test.pl:11:
/home/brandon/projects/sillybin/prolog/foo_test.pl:4:
PL-Unit: Test that_1_is_recognised_as_int: Test succeeded with choicepoint
. done
% All 2 tests passed
% foo_test compiled 0.03 sec, 1,848 clauses
true.
  • 我正在使用 SWI-Prolog(多线程,64 位,版本 6.6.6)
  • 我试过将两者结合起来 count_ints谓词合二为一,使用 ; ,但它仍然产生相同的警告。
  • 我在 Debian 8 上(我怀疑这有什么不同)。

  • 问题
  • 这个警告是什么意思?还有...
  • 我该如何预防?
  • 最佳答案

    首先,让我们忘记整个测试框架,只考虑顶层的查询:

    ?- count_ints(1, 1)。
    真的 ;
    错误的。

    这个交互告诉你,在第一个解决方案之后,一个 选择点离开了。这意味着 替代品 有待尝试,并尝试回溯。在这种情况下,没有其他解决方案,但系统无法在实际尝试之前告知这一点。

    使用 all/1测试用例选项

    有多种方法可以修复警告。一个直接的方法是像这样说明测试用例:

    test('that_1_is_recognised_as_int', all(Count = [1])) :-
    count_ints(1, Count)。

    这隐含收集 所有解决方案 ,然后立即对所有这些内容发表声明。

    使用 if-then-else

    一个更智能的解决方案是使 count_ints/2本身是确定性的!

    一种方法是使用 if-then-else,如下所示:

    count_ints(X, 答案) :-
    ( 整数(X) -> 答案 = 1
    ;答案 = 0
    )。

    我们现在有:

    ?- count_ints(1, 1)。
    真的。

    即,查询现在确定性地成功。

    纯解决方案:清理数据结构

    然而 ,最优雅的解决方案是使用 干净的表示 ,以便您和 Prolog 引擎可以通过 区分所有情况模式匹配 .

    例如,我们可以 将整数表示为 i(N) ,以及其他所有内容 other(T) .

    在这种情况下,我使用包装器 i/1other/1来区分情况。

    现在我们有:

    count_ints(i(_), 1)。
    count_ints(其他(_),0)。

    测试用例可能如下所示:

    测试('that_1_is_recognised_as_int'):-
    count_ints(i(1), 1)。

    测试('that_atom_is_not_recognised_as_int'):-
    count_ints(其他(任意),0)。

    这也没有警告地运行,具有显着优势,代码实际上可以用于生成 答案:

    ?- count_ints(Term, Count)。
    项 = i(_1900),
    计数 = 1 ;
    期限 = 其他(_1900),
    计数 = 0。

    相比之下,我们有其他版本:

    ?- count_ints(Term, Count)。
    计数 = 0。

    不幸的是,最多只能考虑覆盖 50% 的可能情况......

    更严格的限制

    正如鲍里斯在评论中正确指出的那样,我们可以通过 使代码更加严格。约束 i/1的论据条款到 整数 .例如,我们可以这样写:

    count_ints(i(I), 1) :- I inf..sup.
    count_ints(其他(_),0)。

    现在,论点 必须是 一个整数,它会通过以下查询变得清晰:

    ?- count_ints(X, 1)。
    X = i(_1820),
    _1820 inf..sup。

    ?- count_ints(i(any), 1)。
    错误:类型错误:应为“整数”,找到“任何”(原子)

    请注意,鲍里斯提到的示例在没有如此严格的约束的情况下也失败了:

    ?- count_ints(X, 1), X = 任何东西。
    错误的。

    尽管如此,在参数上添加更多约束通常很有用,如果您需要对整数进行推理,CLP(FD) 约束通常是一个很好的通用解决方案,可以显式声明类型约束,否则这些约束只能隐含在您的程序中。

    请注意 integer/1没有得到备忘录:

    ?- inf..sup 中的 X,整数(X)。
    错误的。

    这表明,虽然 X毫无疑问地限于 整数 在本例中,integer(X)仍然没有成功。因此,您不能使用像 integer/1 这样的谓词。等作为可靠的检测器类型。依靠模式匹配和使用约束来增加程序的通用性要好得多。

    关于unit-testing - 什么是 PL-Unit 中的 "Test succeeded with choicepoint"警告,我该如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40711908/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com