使用不纯原语的 Prolog 谓词的纯度
Purity of Prolog predicates that use impure primitives
我知道 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).
我有两个问题:
- 上面的谓词
plus/3
真的很纯粹吗?
- 一般来说,如何证明特定关系具有逻辑纯度?
这个问题是在 answer 的讨论之后提出的。
关于问题"is the above plus/3
really pure?"我只能说:我不知道这里保留了哪些属性,因为代码,由于所有这些额外的逻辑谓词,非常复杂且难以理解,以至于它很难说它实际上在做什么。在这种情况下,我真的必须说 doing,因为这远非 describing 我们可以相对轻松地谈论的声明性代码。在这种情况下,我们期望从声明性代码获得的各种属性都可能被破坏。
通常证明关系是纯关系的最佳方法是将自己限制在 Prolog 的 pure 和 monotonic 子集。正是因为这个原因,这个属性才这么重要,因为这个子集在组合下是封闭的。一旦你离开这个子集,很快就很难证明你的程序的任何属性,正如你的例子很好地证明的那样。
例如,要证明你的 plus/3
单调,你需要证明,除其他外,如果 ?- plus(X, _, _), X = T
失败 任何术语 T
,那么 ?- X = T, plus(X, _, _)
不成功 。由于通常无法确定查询是失败、循环还是成功,因此我们通常甚至无法确定此蕴涵的单方面,更不用说两方面了,我只能说:祝你好运!
- Is the above predicate plus/3 really pure?
它有一些奇怪的行为:有时它接受算术表达式,有时不接受;这虽然所有参数都被评估:
?- 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
我宁愿担心 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 ...
所以,在我看来你的定义是纯粹的。然而,正是这种编程风格使得很难保证这一点 属性。一个微小的改变都会造成灾难性的后果。
- In general, how can you prove that a particular relation has logical purity?
最简单的方法是构造。也就是说,仅使用纯单调构建块。即,Prolog 没有任何内置函数,仅使用常规目标的合取和析取。以这种方式构建的任何程序也将是纯粹和单调的。
然后,执行此程序,将 Prolog 标志发生检查设置为 true
或 error
.
添加到 (=)/2
和 dif/2
等纯内置插件。
添加尝试模拟纯关系并在无法模拟时产生实例化错误的内置函数。想想 (is)/2
和算术比较谓词。其中一些非常接近边界,例如 call/N
可能会调用一些不纯的谓词。
添加 library(clpfd)
并将标志 clpfd_monotonic
设置为 true
。
许多结构对于某些用途来说是好的和纯的,但对于其他用途来说是不纯的。想想 if-then-else,它非常适合算术比较:
..., ( X > Y -> ... ; ... ), ...
但不能与像
这样的纯目标一起工作
..., ( X = Y -> ... ; ... ), ... % impure
剩下的是不纯的内置函数,可用于构造以纯方式运行的谓词;但其定义不再纯粹。
例如,考虑真正的绿色切割。这些非常罕见,在 SO 上更罕见。参见 this and that。
另一种提供纯关系的常见模式是条件句,例如:
..., ( var(V) -> something with var ; the equivalent with nonvar ), ...
并且为了防止未完全覆盖的情况,可能会抛出错误。
我知道 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).
我有两个问题:
- 上面的谓词
plus/3
真的很纯粹吗? - 一般来说,如何证明特定关系具有逻辑纯度?
这个问题是在 answer 的讨论之后提出的。
关于问题"is the above plus/3
really pure?"我只能说:我不知道这里保留了哪些属性,因为代码,由于所有这些额外的逻辑谓词,非常复杂且难以理解,以至于它很难说它实际上在做什么。在这种情况下,我真的必须说 doing,因为这远非 describing 我们可以相对轻松地谈论的声明性代码。在这种情况下,我们期望从声明性代码获得的各种属性都可能被破坏。
通常证明关系是纯关系的最佳方法是将自己限制在 Prolog 的 pure 和 monotonic 子集。正是因为这个原因,这个属性才这么重要,因为这个子集在组合下是封闭的。一旦你离开这个子集,很快就很难证明你的程序的任何属性,正如你的例子很好地证明的那样。
例如,要证明你的 plus/3
单调,你需要证明,除其他外,如果 ?- plus(X, _, _), X = T
失败 任何术语 T
,那么 ?- X = T, plus(X, _, _)
不成功 。由于通常无法确定查询是失败、循环还是成功,因此我们通常甚至无法确定此蕴涵的单方面,更不用说两方面了,我只能说:祝你好运!
- Is the above predicate plus/3 really pure?
它有一些奇怪的行为:有时它接受算术表达式,有时不接受;这虽然所有参数都被评估:
?- 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
我宁愿担心 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 ...
所以,在我看来你的定义是纯粹的。然而,正是这种编程风格使得很难保证这一点 属性。一个微小的改变都会造成灾难性的后果。
- In general, how can you prove that a particular relation has logical purity?
最简单的方法是构造。也就是说,仅使用纯单调构建块。即,Prolog 没有任何内置函数,仅使用常规目标的合取和析取。以这种方式构建的任何程序也将是纯粹和单调的。
然后,执行此程序,将 Prolog 标志发生检查设置为 true
或 error
.
添加到 (=)/2
和 dif/2
等纯内置插件。
添加尝试模拟纯关系并在无法模拟时产生实例化错误的内置函数。想想 (is)/2
和算术比较谓词。其中一些非常接近边界,例如 call/N
可能会调用一些不纯的谓词。
添加 library(clpfd)
并将标志 clpfd_monotonic
设置为 true
。
许多结构对于某些用途来说是好的和纯的,但对于其他用途来说是不纯的。想想 if-then-else,它非常适合算术比较:
..., ( X > Y -> ... ; ... ), ...
但不能与像
这样的纯目标一起工作 ..., ( X = Y -> ... ; ... ), ... % impure
剩下的是不纯的内置函数,可用于构造以纯方式运行的谓词;但其定义不再纯粹。
例如,考虑真正的绿色切割。这些非常罕见,在 SO 上更罕见。参见 this and that。
另一种提供纯关系的常见模式是条件句,例如:
..., ( var(V) -> something with var ; the equivalent with nonvar ), ...
并且为了防止未完全覆盖的情况,可能会抛出错误。