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

使用不纯原语的Prolog谓词的纯度,prolog,logic-programming,logical-purity,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

我知道
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).
%nat(X)是真的,如果X是一个自然数
nat(0)。
nat(X):-NONR(X)!,X>0。
nat(X):-nat(X1),X是X1+1。
%如果A、B和C是自然数且A+B=C,则加(A、B、C)为真
加上(A、B、C):-
nat(A),
(不正确(C),C
我有两个问题:

  • 上面的谓词
    plus/3
    真的是纯的吗
  • 一般来说,您如何证明特定关系具有逻辑纯度

  • 这个问题在讨论之后。

    关于“上面的
    plus/3
    真的是纯的吗?”我只能说:我不知道这里保留了哪些属性,因为代码,由于所有这些额外的逻辑谓词,是如此复杂和难以理解,以至于很难知道它实际上在做什么。在这种情况下,我真的必须说这样做,因为这远远不是描述我们可以相对容易地谈论的东西的声明性代码。在这种情况下,我们期望从声明性代码中获得的所有类型的属性都可能被破坏

    一般来说,证明关系是纯的最好方法是将自己限制在纯单调的Prolog子集上。正是由于这个原因,这个属性非常重要,因为这个子集在composition下是封闭的。一旦离开这个子集,很快就很难证明程序的任何属性,正如您的示例很好地演示的那样

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

  • 上面的谓词plus/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
    
    所以,在我看来,你的定义是纯粹的。然而,这种编程风格使得很难保证这种特性。一个微小的变化就会产生灾难性的影响

  • 一般来说,您如何证明特定关系具有逻辑纯度
  • 最简单的方法是建造。也就是说,只使用纯单调的构建块。也就是说,Prolog没有任何内置程序,只使用常规目标的连接和分离。以这种方式构建的任何程序都将是纯粹而单调的。 然后,在Prolog标志出现检查设置为
    true
    error
    的情况下执行该程序

    添加到这个纯内置程序中,如
    (=)/2
    dif/2

    此外,还添加了一些内置代码,这些内置代码尝试模拟纯关系,但无法模拟时会产生实例化错误。想想
    (is)/2
    和算术比较谓词。其中一些非常接近于边界,比如
    call/N
    ,它可能会调用一些不纯净的谓词

    添加
    库(clpfd)
    ,并将标志设置为
    true

    许多构造在某些用途上是精细和纯粹的,但在其他用途上是不纯净的。考虑一下if-then-else,它是算术比较的最佳选择:

     ..., ( X > Y -> ... ; ... ), ...
    
    但这并不能与一个纯粹的目标如

     ..., ( X = Y -> ... ; ... ), ...  % impure
    
    剩下的是不纯的内置代码,可以用来构造行为纯粹的谓词;但其定义不再是纯粹的

    作为一个例子,考虑真正的绿色削减。这是非常罕见的,在这里更是罕见。见和

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

    ..., ( var(V) -> something with var ; the equivalent with nonvar ), ...
    

    为了防止未明确覆盖的案例,可以抛出错误。

    勇敢的问题-->+1!绿色切割不会改变程序的输出。它们可能缺失,解决方案也可能相同。我说的是使用红切的程序(如问题中的那些)。[red]切和
    nonvar/1
    在我的程序终止规则中是必不可少的。我认为代码很容易掌握,我试图实现我能想到的最简单的关系。我对那些“许多其他的东西”感兴趣。其中一些其他的东西是:3个参数中的每一个都具有相同的属性。然后针对3个参数及其任何子项之间的每个可能的别名。然后,对于所有这些统一的每个可能分区,关于它们在调用之前或之后的位置。然后所有这些情况都以其他3种方式出现:如果X成功,那么Y不会失败;加上另一方向的相应测试。在所有这些情况下,对无穷多个项的所有这些测试。你写下“如果?-plus(X,,,,,X=T对任何项T都失败,那么?-X=T,plus(X,,,,[must]not successful]”这里是一个变量吗?这不是一个更具体的术语吗?在调用
    plus
    专门化之前是否指定X?也许那句话有点离题,或者我不明白。为什么
    plus(X,{,},X=T
    X=T,plus(X,{,})
    更一般?是的,我在本例中主要考虑了
    X
    是一个变量的小特例,但该属性当然必须适用于所有术语
    X
    ,包括v
    ..., ( var(V) -> something with var ; the equivalent with nonvar ), ...