【问题标题】:Prolog - 2 ways for progenitor predicate implementationProlog - 祖谓词实现的 2 种方法
【发布时间】:2016-02-17 23:02:21
【问题描述】:

给定一组通过谓词parent/2表示父子关系的事实,用谓词pred1/定义关系“祖先”(祖先)时有什么区别2pred2/2如下图?

pred1(X,Z) :- parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z).

pred2(X,Z) :- parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y).

【问题讨论】:

    标签: prolog parent-child failure-slice transitive-closure


    【解决方案1】:

    主要区别在于两者的终止属性,前提是关系中有一些循环。为了理解这一点,我将使用 failure-slice 将程序缩减为 w.r.t 的本质。终止。

    pred1(X,Z) :- false, parent(X,Z)。 pred1(X,Z) :- 父级(X,Y), pred1(Y,Z)。 % Z 没有影响 pred2(X,Z) :- false, parent(X,Z)。 pred2(X,Z) :- 父级(Y,Z), pred2(X,Y)。 % X 没有影响

    对于pred1/2,第二个参数对终止完全没有影响,而在pred2/2,第一个参数没有影响。要看到这一点,请尝试使用事实的原始定义:

    父母(一,一)。 ?- pred1(b, _), false。 % 终止 ?- pred2(b, _), false。 % 循环 ?- pred1(_, b), false。 % 循环 ?- pred2(_, b), false。 % 终止

    请参阅closure/3,了解避免此类循环的一般方法。

    为了完整起见,这里是传递闭包的另一种变体,它具有一些概念优势:

    pred3(X,Z) :- parent(X,Z).
    pred3(X,Z) :- pred3(X,Y), pred3(Y,Z).
    

    唉,它的终止特性最差。事实上,它从不终止,正如以下片段所证明的那样:

    pred3(X,Z) :- false, parent(X,Z)。 pred3(X,Z) :- pred3(X,Y), false, pred3(Y,Z)

    在这个片段中,第一个参数只被传递。所以,不管参数是什么,程序都会一直循环!

    ?- pred3(b,b), false。 % 循环

    【讨论】:

      猜你喜欢
      • 2014-01-26
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多