Prolog中的否定作为失败是一种过程行为吗?

Prolog中的否定作为失败是一种过程行为吗?,prolog,answer-set-programming,negation-as-failure,Prolog,Answer Set Programming,Negation As Failure,我对Prolog语言中作为失败的否定有一点疑问: 这是一个理论多于实际的问题,因为我清楚这个例子是如何工作的 因此,我有以下Prolog程序: /* Fatti che specificano quali esseri sono degli animali: */ animal(cat). animal(dog). animal(frog). animal(horse). animal(viper). animal(boa). animal(python). /* Fatti che spec

我对Prolog语言中作为失败的否定有一点疑问:

这是一个理论多于实际的问题,因为我清楚这个例子是如何工作的

因此,我有以下Prolog程序:

/* Fatti che specificano quali esseri sono degli animali: */
animal(cat).
animal(dog).
animal(frog).
animal(horse).
animal(viper).
animal(boa).
animal(python).

/* Fatti che specificano quali esseri sono dei serpenti: */
snake(viper).
snake(boa).
snake(python).

/* X è un serpente, fallisce ed impedisce il backtracking quindi
   il predicato likes(mary,X) risulta essere falso: */
likes(mary,X) :- snake(X),
                 !,
                 fail.

/* Se X è un animale allora a mary piace: */
likes(mary, X) :- animal(X).
在序言中,我不能简单地说:“玛丽爱所有的动物,但不爱蛇” 我必须这样表述:“如果X是蛇,那么玛丽不喜欢它。否则,如果X是动物,玛丽喜欢它”

根据规则,先例程序正是这样做的:

likes(mary,X) :- snake(X),
                 !,
                 fail.
Prolog检查X是否为真,它是一条蛇,施加剪切以避免回溯并强制谓词失败

通过这种方式,如果
snake(X)
TRUE
程序也会强制头部的失败预测
likes(mary,X)
并强制执行回溯,以避免执行程序中的其他规则的可能性(该答案为TRUE,因为蛇也是动物)

我的问题是:我觉得Prolog的这种用法不属于逻辑和声明性范式,在某种程度上属于某种程序范式

因为:

  • 我必须对2谓词施加一个顺序(因此,在某种程度上,我是说:如果第一个谓词失败,请尝试第二个谓词)
  • 但我更想说的是:如果第一个规则匹配(X是一条蛇),那么执行一个强制失败,并且不强制回溯
  • 在我看来,这似乎更接近于一个程序意义,一个经典的逻辑意义


    是吗?在这些情况下,Prolog是否使用过程行为来克服逻辑的限制?

    我不同意“逻辑的限制”

    也会是这样

    likes(mary,X) :- not(snake(X)) , animal(X).
    
    因为Prolog使用深度优先搜索,所以一些内容可以用更短的方式表示,这取决于深度优先搜索回溯算法

    x :- a, !, b.
    x :- c.
    x :- d.
    

    x :- a, b.
    x :- not(a), c.
    x :- not(a), d.
    

    大多数情况下,使用cut(!)的程序都是 对目标和条款的顺序敏感 意义不仅在于它们的终止,它们也是如此 通常不是声明性的

    作为失败的否定(\+)以某种方式被封装 伤口。它是由大多数Prolog定义甚至实现的 系统如下:

    \+ X :- X, !, fail.
    \+ _ .
    
    虽然它暗示了一种逻辑意义,因此具有声明性, 作为失败的否定仍然对顺序很敏感 目标。这里有一个例子。假设我们有以下几点 数据库:

    p(a).
    q(b,c).
    
    然后,以下查询生成X=a作为解决方案:

    ?- p(X), \+ q(X,Y).
    X = a.
    
    但是如果连词(,)/2的参数切换到另一端, 得到了不同的结果:

    ?- \+ q(X,Y), p(X).
    false.
    
    因此,作为失败的否定本身不是声明性的。对于 论点的基本术语流,否定为失败 在存在量词中。因此,对表单的查询:

     ?- A(X), \+ B(X,Y).
    
    本质上是指它量化了新鲜事物 否定中的变量Y:

     ?- A(X), ~ exists Y B(X,Y).
    
    因此,在上面的例子中,连接被切换 当失败发生变化时,否定中的一组新变量,即 为什么会得到不同的解


    拜别< /P>我想补充一下,安德列是正确的,你可以使用Prolog中的过程行为来做一些很难声明的事情——尽管我同意这不是一个难以说明的事情的例子。考虑写为<代码>喜欢(玛丽,X):-动物(x),+蛇(x).<代码>,并回忆一下<代码>(+)。/1(这是一个ISO标准谓词,而

    not/1
    不是)如果其参数为ground,则是正确的。使用此定义,您甚至可以询问最一般的查询
    ?-likes(X,Y)。
    并获得正确的结果。是的,这解决了子句排序问题,即使“a”在运行时是非基础的,并且没有副作用。但实际上,当“a”在运行时不是地面时,它会导致开销,并且不能解决目标排序问题。