【问题标题】:Is there a cut-less way to implement same_length/3?有没有一种无删减的方式来实现same_length/3?
【发布时间】:2018-12-04 15:42:19
【问题描述】:

假设我想断言三个列表的长度相同。我可以这样做:

same_length(First, Second, Third) :-
  same_length(First, Second),
  same_length(Second, Third).

FirstSecond 被实例化时,这是正确的。当所有三个参数都被实例化时,它也可以工作!但是,像 length(Third, 3), same_length(First, Second, Third) 这样的调用会导致它返回带有选择点的正确答案(所有三个列表的长度都为 3),然后永远循环生成永远不会匹配的解决方案。

我写了一个我相信在任何情况下都能做正确事情的版本:

same_length(First, Second, Third) :-
  /* naively calling same_length(First, Second), same_length(Second, Third) doesn't work,
     because it will fail to terminate in the case where both First and Second are
     uninstantiated.
     by always giving the first same_length/2 clause a real list we prevent it from
     generating infinite solutions */
  ( is_list(First), same_length(First, Second), same_length(First, Third), !
  ; is_list(Second), same_length(Second, First), same_length(Second, Third), !
  ; is_list(Third), same_length(Third, First), same_length(Third, Second), !
    % if none of our arguments are instantiated then it's appropriate to not terminate:
  ; same_length(First, Second), same_length(Second, Third) ).

我一直听说应该尽可能避免切割,这里可以避免吗?

作为一个额外的问题,我认为这些是绿色削减,因为最终谓词是完全关系的,这是真的吗?

【问题讨论】:

  • “绿色削减”用于提高程序的效率——它们只是削减不可能导致解决方案的计算。 “红色削减”用于消除不需要的解决方案。它们也提高了效率,但它们也改变了程序的可能输出。换句话说,“绿色剪辑”不会改变程序的含义,但“红色剪辑”是程序的一个组成部分,可以产生预期的结果。
  • 我曾经非常担心这样的情况,并产生了具有很多 var/1ground/1 的类似谓词(这基本上就是您在这里使用 is_list/1 所做的事情) .总是,@false 会出现并指出我的 frankenstein 谓词在奇怪的情况下无法表现的十几种新方式(带有实例化的头部和未实例化的尾部的列表,向后正确性等)现在我只做简单的事情并希望调试如果我在实践中偶然发现一个奇怪的实例化模式会更容易。
  • 顺便说一句,我真的很喜欢你的问题,请继续提问!
  • same_length([_|_], _, []). 循环。
  • @num1:您已经接受了一个答案,所以我认为这就是您想要的答案。我宁愿写maplist(\_^_^_^true, Xs, Ys, Zs)

标签: prolog logical-purity non-termination


【解决方案1】:

为什么不以通常定义same_length/2 的方式定义same_length/3

same_length([], [], []).
same_length([_| T1], [_| T2], [_| T3]) :-
    same_length(T1, T2, T3).

在所有参数未绑定的情况下调用时效果很好:

?- same_length(L1, L2, L3).
L1 = L2, L2 = L3, L3 = [] ;
L1 = [_990],
L2 = [_996],
L3 = [_1002] ;
L1 = [_990, _1008],
L2 = [_996, _1014],
L3 = [_1002, _1020] ;
L1 = [_990, _1008, _1026],
L2 = [_996, _1014, _1032],
L3 = [_1002, _1020, _1038] ;
...

在您提到的情况下,没有虚假的选择点或非终止回溯:

?- length(L3, 3), same_length(L1, L2, L3).
L3 = [_1420, _1426, _1432],
L1 = [_1438, _1450, _1462],
L2 = [_1444, _1456, _1468].

【讨论】:

  • 我正在与一种强烈的诅咒冲动作斗争,因为,哇,我怎么会错过这么简单的解决方案。是的,这显然是正确的方法,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 2023-04-03
  • 1970-01-01
  • 2019-10-20
  • 2021-11-15
  • 2022-09-23
  • 1970-01-01
相关资源
最近更新 更多