【问题标题】:Checking if a number is triangular检查数字是否为三角形
【发布时间】:2020-04-17 21:52:02
【问题描述】:

所以我有这个谓词 triangular(N),其中 N 是一个数字,如果一个数字是一个三角形数字,这个谓词返回 true。

我的问题是,由于某种原因,我的谓词执行了一个无限循环,而不是仅仅将数字相加直到 N。

例子:

?- 三角形(3)。 3 真的

它并没有结束。

所以基本上这是将数字的总和直到 3,但它在做一些我不明白的事情。

程序:

triangular(N) :- triangular(N,0).

triangular(N,AC) :- triangular(N,AC,N).

triangular(N,AC,0) :-  write(AC).

triangular(N,AC,CONT) :- NCONT is CONT - 1,
                         NAC is AC + NCONT,
                         triangular(N,NAC,NCONT).

【问题讨论】:

    标签: prolog triangular


    【解决方案1】:

    背景信息

    Prolog 可以为您的查询搜索不止一种解决方案。

    考虑这个程序:

    human(alice).
    human(bob).
    

    当您查询?- human(X). 时,Prolog 将搜索与您的程序匹配的X 的分配。它将向您展示解决方案X = alice。之后,您可以按. 停止搜索,也可以按; 继续搜索。如果继续,Prolog 会找到X = bob。之后它将停止,因为它已经用尽了所有可能的解决方案:

    ?- human(X).
    X = alice .
    
    ?- human(X).
    X = alice ;
    X = bob.
    

    您可以使用剪切谓词! 控制搜索过程。 cut 谓词切断当前层中的替代路径。所以如果你用这条规则扩展上面的程序:

    find_first_human(X) :- human(X), !.
    

    运行查询?- find_first_human(X).只会输出X = alice.,不会搜索更多答案。 Prolog 知道 human(X) 可以通过多种方式解决,但随后 ! 告诉 Prolog 忽略这些替代方案。

    将此应用到您的程序中

    主要问题是您的最后一个triangle 谓词不需要CONT > 0。因此,当您查询?- triangle(3). 时,Prolog 最终会到达triangular(3,3,0).,它与您的write 规则相匹配。如您所见,您的程序按预期输出3。但是,Prolog 然后发现triangular(3,3,0) 有替代解决方案,因此它提供您继续搜索。您可以按. 停止,或按; 继续。如果你继续,Prolog 将尝试triangular 的最后一条规则,CONT 被解析为0。因此NCONT 变为-1。然后这将进入一个无限循环,其中最后一个 triangular 规则被重复应用,不断递减 CONT

    您可以使用trace. 验证这一点(可以再次使用notrace. 禁用):

    ?- trace.
    ?- triangular(3).
       Call: (8) triangular(3) ? creep
       Call: (9) triangular(3, 0) ? creep
       Call: (10) triangular(3, 0, 3) ? creep
    ...
       Call: (13) triangular(3, 3, 0) ? creep
       Call: (14) write(3) ? creep
    3
       Exit: (14) write(3) ? creep
       Exit: (13) triangular(3, 3, 0) ? creep
    ...
    true ;
       Redo: (13) triangular(3, 3, 0) ? creep
       Call: (14) _2076 is 0+ -1 ? creep
       Exit: (14) -1 is 0+ -1 ? creep
    ...
    

    您可以通过将最后一条规则更改为:

    triangular(N,AC,CONT) :- CONT > 0,
                             NCONT is CONT - 1,
                             NAC is AC + NCONT,
                             triangular(N,NAC,NCONT).
    

    这禁止 Prolog 应用 triangular(3,3,0) 的规则。当您使用修改后的程序运行查询?- triangular(3). 时,Prolog 应该在到达triangular(3,3,0) 时像以前一样写出3。之后,它检测到可能存在替代解决方案。如果您按;,它会检测到最后一条规则无法应用,因为CONT > 0 约束不成立。然后它停止搜索:

    ?- triangular(3).
    3
    true ;
    false.
    

    我们可以使用上一节中显示的切割谓词! 进一步简化这一点,将write 规则修改为:

    triangular(N,AC,0) :-  write(AC), !.
    

    这告诉 Prolog 不要搜索 triangular(3,3,0) 的替代解决方案。当您运行查询 ?- triangular(3). 时,Prolog 应该像以前一样写出 3,然后退出而不进一步搜索:

    ?- triangular(3).
    3
    true.
    

    【讨论】:

      猜你喜欢
      • 2012-04-26
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2012-11-03
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多