避免在谓词中递归

时间:2015-06-15 18:34:39

标签: prolog

我对以下谓词有以下问题,如何从两个谓词中删除递归调用f(T,S1)

流量模型: (I,O)

f([],0).
f([H|T],S):-
    f(T,S1),
    S1 > 2,!,
    S is S1 + H.
f([_|T],S):-
    f(T,S1),
    S is S1 + 1.

这是一个棘手的问题,我对prolog并不是那么好。第二个谓词总是失败。=>可以下垂,但第二个怎么样。正如我所见,这个方法是一个列表元素计数器。感谢。

这甚至可能吗?

2 个答案:

答案 0 :(得分:3)

好的,这是一个复杂的问题。你认为这是一个技巧问题,但它真的是一个吗?我们怎么能确定?我会让library(clpfd)为我做思考。首先,我将重写您的程序:

:- use_module(library(clpfd)).

fx([],0).
fx([H|T],S):-
    fx(T,S1),
    S1 #> 2,
    S #= S1 + H.
fx([_|T],S):-
    fx(T,S1),
    S1 #=< 2,
    S #= S1 + 1.

(并且只是一句话:在递归两次之后进行这些测试会使这个程序需要指数级的推论,但让我们坚持下去......)

所以我想以最一般的方式推理该计划。因此,我不会采取具体的价值观,然后试图找出一个理论。相反,我会问一些非常一般的问题(使用SICStus):

| ?- assert(clpfd:full_answer).
yes
| ?- length(L,N), fx(L,S).
   L = [],
   N = 0,
   S = 0 ?
;
   L = [_A],
   N = 1,
   S = 1 ?
;
   L = [_A,_B],
   N = 2,
   S = 2 ?
;
   L = [_A,_B,_C],
   N = 3,
   S = 3 ?
;
   L = [_A,_B,_C,_D],
   N = 4,
   _A+3#=S,
   _A in inf..sup,
   S in inf..sup ?
;
   L = [_A,_B,_C,_D,_E],
   N = 5, ...

所以,请查看N = 0N = 3的答案:没有任何约束,实际上列表[_A,_B,...]的所有元素都会被忽略。但是,从N = 4开始,第一个元素_A现在会影响&#34;总和&#34; S,因为等式S #= _A+3成立!随着价值的增加,事情变得越来越复杂。

在任何情况下,我都看不出这可能是一个棘手的问题。最后三个元素被忽略。嗯,那是一种诡计。但是否则元素(或至少其中一些元素)会影响结果!

答案 1 :(得分:2)

以下怎么样?这很有效率! - )

f([],0).
f([H|T],S):-
    f(T,S1),
    (  S1 > 2
    -> S is S1 + H
    ;  S is S1 + 1
    ).