Prolog的纯度谓词使用不纯的原语

Tud*_*riu 8 prolog logic-programming logical-purity

我知道这一点var/1,nonvar/1并且!/0是不纯的基元,但它们的使用是否会使每个使用它们的程序都不纯净?

我写了下面的谓词plus/3,表现得好像是纯粹的,或者至少是我声称的那样.谓词是示范性的,不是为了提高效率.

% nat(X) is true if X is a natural number

nat(0).
nat(X):- nonvar(X), !, X > 0.
nat(X):- nat(X1), X is X1 + 1.

% plus(A, B, C) is true if A,B and C are natural numbers and A+B=C

plus(A, B, C):-
    nat(A),
    (nonvar(C), C < A, !, false ; true),
    plus_(B, A, C).

plus_(A, B, C):-
    nat(A),
    (nonvar(C), C < A, !, false ; true),
    C1 is A + B,
    (C = C1 ; nonvar(C), C < C1, !, false).
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  1. 上面的谓词plus/3真的很纯粹吗?
  2. 一般来说,如何证明特定关系具有逻辑纯度?

这个问题跟随对这个答案的讨论.

fal*_*lse 7

  1. 上面的谓词加上/ 3真的很纯粹吗?

它有一些奇怪的行为:有时它接受算术表达式,有时不接受; 虽然评估了所有参数:

?- plus(3,5-3,5).
true ...

?- plus(3,2,3+2).
false.

?- plus(3,2,3+b).
ERROR: </2: Arithmetic: `b/0' is not a function

?- plus(3,2,3+Z).
ERROR: </2: Arguments are not sufficiently instantiated
Run Code Online (Sandbox Code Playgroud)

我宁愿担心nat/1案件的效率低下,例如:

?- time( ( nat(X), X > 9999 ) ).
% 50,025,002 inferences, 27.004 CPU in 27.107 seconds (100% CPU, 1852480 Lips)
X = 10000 ;
% 10,006 inferences, 0.015 CPU in 0.015 seconds (99% CPU, 650837 Lips)
X = 10001 ;
% 10,005 inferences, 0.016 CPU in 0.016 seconds (99% CPU, 631190 Lips)
X = 10002 ...
Run Code Online (Sandbox Code Playgroud)

所以,我认为你的定义是纯粹的.但是,这种编程风格使得很难保证这个属性.最小的改变将带来灾难性的后果.

  1. 一般来说,如何证明特定关系具有逻辑纯度?

最简单的方法是施工.也就是说,仅使用纯粹的单调构建块.也就是说,Prolog没有任何内置插件,仅使用常规目标的连接和分离.以这种方式构建的任何程序也将是纯粹和单调的.然后,执行此程序与Prolog标志发生检查设置为trueerror.

添加到这个纯粹的内置插件喜欢(=)/2dif/2.

添加到此内置函数,尝试模拟纯关系,并在无法执行时生成实例化错误.想想(is)/2和算术比较谓词.其中一些完全处于边缘状态call/N,可能会称之为不纯的谓词.

添加library(clpfd)标志clpfd_monotonic设置为true.

许多结构对于某些用途来说是精细和纯净的,但对其他人来说是不纯的.想想if-then-else,它非常适合算术比较:

 ..., ( X > Y -> ... ; ... ), ...
Run Code Online (Sandbox Code Playgroud)

但是它与纯粹的目标并不一致

 ..., ( X = Y -> ... ; ... ), ...  % impure
Run Code Online (Sandbox Code Playgroud)

剩下的是不纯的内置函数,可用于构造以纯粹方式运行的谓词; 但其定义不再纯粹.

举个例子,考虑真正的绿色削减.这些非常罕见,甚至在SO上也很少见.看到这个那个.

另一种提供纯关系的常见模式是条件:

..., ( var(V) -> something with var ; the equivalent with nonvar ), ...
Run Code Online (Sandbox Code Playgroud)

为防止未完全覆盖的案例,可能会引发错误.


mat*_*mat 6

关于"上面plus/3真的是纯粹的吗?" 这个问题.我只能说:我不知道这里保留了哪些属性,因为由于所有这些超逻辑谓词,代码是如此复杂且难以理解,因此很难说它实际上在做什么.我真的必须说在这种情况下,因为这远远不是描述我们可以比较容易谈论的东西的声明性代码.在这种情况下,我们期望从声明性代码中获得的各种属性可能会被破坏.

通常证明关系纯粹的最好方法是将自己限制在Prolog 的纯粹单调子集中.出于这个原因,这个属性非常重要,因为这个子集在组合下是封闭的.一旦你离开这个子集,很快就很难证明你的程序的任何属性,正如你的例子很好地演示.

例如,为了证明你的plus/3单调性,你需要在许多其他事情中表明,如果任何一个术语?- plus(X, _, _), X = T 失败T,那么?- X = T, plus(X, _, _)不会成功.由于查询失败,循环或成功通常是不可判定的,因此我们通常甚至无法确定这一含义的单方面,更不用说两者,我只能说:祝你好运!

  • 这些许多其中的一些是:3个参数中的每一个都具有相同的属性.然后对于3个参数和它们的任何子项之间的每个可能的别名.然后,对于在呼叫之前或之后关于它们的放置的所有这些统一的每个可能的划分.然后在其他3种方式中所有这些情况:如果X成功,那么Y不会失败; 加上另一个方向的相应测试.在所有这些情况下,所有这些测试都包含无限的术语. (3认同)
  • 是的,我在本例中主要考虑了一个小的特殊情况`X`是一个变量,但该属性当然必须保持*all*terms`X`,*包括*变量,否则我们不能调用谓词a真正的关系.同样,它必须保持"T"为*任何*项,不一定是地.真正的专业化只是添加额外的约束,例如比较`? - 加(A,_,_).`与`? - A = Term,加上(A,_,_).如果后者成功,那么前者也必须如此,否则我们不能称之为真正的关系.同样,交换性(`A,B` =`B,A`)也必须*保留. (3认同)