【问题标题】:Can you write between/3 in pure prolog?你能用纯序言写 between/3 吗?
【发布时间】:2013-08-20 14:10:29
【问题描述】:

我一直试图了解如何从 Prolog 谓词中的回溯生成一系列值。内置谓词 between/3 将在回溯时一次生成一个范围内的所有整数,因此一个如何编写的示例可能对我的任务有所帮助。

我在现有的 Prolog 系统中寻找了一个实现,但是 GNU Prolog 的 between/3 的实现是一个 C 函数,其中的诀窍是它调用另一个 C 函数“Pl_Create_Choice_Point”,它允许它产生附加值关于回溯。

【问题讨论】:

    标签: prolog backtracking


    【解决方案1】:
    bet(N, M, K) :- N =< M, K = N.
    bet(N, M, K) :- N < M, N1 is N+1, bet(N1, M, K).
    

    在行动:

    $ swipl
    ?- [bet].
    % bet compiled 0.00 sec, 1,064 bytes
    true.
    
    ?- bet(1,5, K).
    K = 1 n
    K = 2 n
    K = 3 n
    K = 4 n
    K = 5 n
    false.
    

    如果使用cut,则可以防止最终搜索失败,并恢复确切的内置 between/3 行为:

    bet(N, M, K) :- N < M, K = N.
    bet(N, M, K) :- N == M, !, K = N.
    bet(N, M, K) :- N < M, N1 is N+1, bet(N1, M, K).
    

    在行动:

    ?- [bet].
    % bet compiled 0.00 sec, 416 bytes
    true.
    
    ?- between(1,5,K).
    K = 1 n
    K = 2 n
    K = 3 n
    K = 4 n
    K = 5.
    
    ?- [bet].
    % bet compiled 0.00 sec, 240 bytes
    true.
    
    ?- bet(1,5,K).
    K = 1 n
    K = 2 n
    K = 3 n
    K = 4 n
    K = 5.
    

    【讨论】:

    • 您的初始版本要好一些,因为它最终没有失败。
    【解决方案2】:

    您真正要问的是如何创建选择点。只要你有一个成功的统一,你就会得到一个解决方案。这就是@seanmcl 的第一个谓词中发生的情况:

    bet(N, M, K) :- N =< M, K = N.
    

    要获得选择点,您需要有替代方案。在 Prolog 中只有两种方法可以替代:使用明确的“或”:;,或者提供另一个规则。 @seanmcl 的代码给出了另一个规则,这是这种情况的惯用语。

    再举一个例子,member/2 为列表中的每个项目生成一个解决方案,但不需要神奇的 C 函数,只需两条规则:

    member(X, [X|_]).
    member(X, [_|Xs]) :- member(X, Xs).
    

    让我们看看member(X, [1,2]) 会发生什么。首先使用第一条规则,将[X|_][1,2]统一,产生X=1_=[2]。这是一个成功的统一,因此产生了一个解决方案。如果失败(例如在控制台上按;),则会启动回溯。下一个选择点在两条规则之间,所以输入下一条规则。 [_|Xs] 与 [1,2] 结合,产生绑定 Xs=[2],然后调用 member(X, [2])。重新进入时,可以再次做出相同的决定,因此应用第一条规则member(X, [X|_]) 并生成X=2 绑定。这是一个解决方案。如果你再次回溯,你将得到一个无害的失败,因为这两个规则都没有与[] 统一。

    我希望这有助于稍微了解情况。

    【讨论】:

      猜你喜欢
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      • 2014-06-07
      • 2011-05-31
      • 1970-01-01
      相关资源
      最近更新 更多