List 如何在prolog中的列表中存储递归函数的值?

List 如何在prolog中的列表中存储递归函数的值?,list,recursion,prolog,List,Recursion,Prolog,我的任务是: 给出函数f的以下定义,创建一个Prolog程序来计算所有020的值需要花费很长时间 请让我知道如何将值存储在列表中以加快程序运行。无需存储超过前两个数字 这是我从臀部快速而肮脏的射门: p3(N,F) :- ( N =:= 0 -> F = 0 ; N =:= 1 -> F = 1 ; N > 1 -> N0 is N-2, p3_(N0,0,1,F) ). p3_(N,F0,F1,F) :- F2 is F0 + 2*F1, (

我的任务是:

给出函数f的以下定义,创建一个Prolog程序来计算所有0
  • f(0)=0
  • f(1)=1
  • 当n>1时,f(n)=f(n-2)+2*f(n-1)
到目前为止,我的代码是:

problemThree(0, 0).
problemThree(1, 1).
problemThree(N, NF) :-
    N > 1,
    A is N - 2,
    B is N - 1,
    problemThree(A, AF),
    problemThree(B, BF),
    NF is AF + 2*BF.
它正在工作,但显示N>20的值需要花费很长时间


请让我知道如何将值存储在列表中以加快程序运行。

无需存储超过前两个数字

这是我从臀部快速而肮脏的射门:

p3(N,F) :- ( N =:= 0 -> F = 0 ; N =:= 1 -> F = 1 ; N > 1 -> N0 is N-2, p3_(N0,0,1,F) ). p3_(N,F0,F1,F) :- F2 is F0 + 2*F1, ( N =:= 0 -> F2 = F ; N0 is N-1, p3_(N0,F1,F2,F) ). 够快吗

?- time((between(0,1000,N), p3(N,_), false)).
% 2,006,005 inferences, 0.265 CPU in 0.265 seconds (100% CPU, 7570157 Lips)
false.

以下是一种DCG方法,它将序列生成为列表:

prob3(1, F0, F1) --> [F0, F1].
prob3(N, F0, F1) --> {N > 1, F2 is 2*F1 + F0, N1 is N-1}, [F0], prob3(N1, F1, F2).

prob3(0, [0]).
prob3(N, FS) :-
    phrase(prob3(N, 0, 1), FS).

?- prob3(10, L).
L = [0, 1, 2, 5, 12, 29, 70, 169, 408, 985] ;
false.

?- prob3(169, L).
L = [1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025,
..., 17280083176824678419775054525017769508908307965108250063833395641] ;
false

?- time((prob3(1000, L),false)).
% 3,011 inferences, 0.005 CPU in 0.005 seconds (100% CPU, 628956 Lips)
false.

请注意,对于长列表答案,SWI Prolog将缩写输出,例如:

?- prob3(20, L).
L = [0, 1, 2, 5, 12, 29, 70, 169, 408|...]
这只是SWI Prolog的方法,它不让屏幕上有大量的输出。在这里,您可以使用
w
进行响应,它将给出整个结果:

?- prob3(20, L).
L = [0, 1, 2, 5, 12, 29, 70, 169, 408|...] [write]   % PRESSED 'w' here
L = [0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025, 470832, 1136689, 2744210, 6625109, 15994428] ;
false

?-

请看,.

虽然它比其他答案慢得多,但我喜欢这个带有函数精神的答案:

:- use_module(library(lambda)).

f(N, FN) :-
    cont_f(N, _, FN, \_^Y^_^U^(U = Y)).

cont_f(N, FN1, FN, Pred) :-
    (   N < 2 ->
        call(Pred, 0, 1, FN1, FN)
    ;
        N1 is N - 1,
        P = \X^Y^Y^U^(U is X + 2*Y),
        cont_f(N1, FNA, FNB, P),
        call(Pred, FNA, FNB, FN1, FN)
    ).
:-使用_模块(库(lambda))。
f(N,FN):-
续f(N,FN,Y^(U=Y))。
续(N,FN1,FN,Pred):-
(N<2->
调用(Pred、0、1、FN1、FN)
;
N1是N-1,
P=\X^Y^Y^U^(U是X+2*Y),
续(N1、FNA、FNB、P),
呼叫(Pred、FNA、FNB、FN1、FN)
).

记忆很有用,我用它来加速使用Erathostenes筛的素数计算

?- time((between(0,1000,N), prob3(N,_), false)).
% 10,939 inferences, 0.011 CPU in 0.012 seconds (99% CPU, 951780 Lips)

:- dynamic memo/2.
prob3(0, 0).
prob3(1, 1).
prob3(N, R) :- memo(N, R), !.
prob3(N, R) :-
    N > 1, N2 is N-2, N1 is N-1, prob3(N2,R2), prob3(N1,R1), R is R2+2*R1, assertz(memo(N, R)).

性能“繁荣”的原因是,所需的时间是每个值的指数
n
,因为每次计算需要深入递归两次@repeat显示了通过保留最后两个计算值来解决此问题的解决方案,这样它们就不需要重新计算。这是递归斐波那契式计算中的一种常见技术。是时候用Prolog一劳永逸地解决“线性递归”问题了:)非常感谢您的回答(X)。记忆一元函数绝对应该是一个常见的序言习语!允许施加资源限制的东西(使用一些基于LRU的替换方案)。什么是一个好的API呢?嘿,非常感谢你的回答,我尝试过使用它,但我得到了一个错误:错误:prob3/2:未定义的过程:memo/2异常:(8)memo(25,_G977)?你需要声明
:-dynamic memo/2。
只是一个建议:如果缺少3个参数,请使用变量
Pred\u 3
。这个
调用(Pred_3,A,B,C)
是有效的。@false对不起,我不明白你的意思:(你可以使用元参数的特殊命名约定向你的程序添加更多信息。对于可以直接调用的目标,你可以说
目标_0
,因此
调用(目标_0)
。对于缺少一个参数的目标,说
Goal\u 1
,它将被称为
call(Goal\u 1,X)
。在你的例子中,
P
变量可以是
P_4
,就像
Pred_4
一样。好的,现在我明白了。我想我在代码中遗漏了什么。我只得到了9个值,之后它会显示一个竖线,并停止如下操作:?-prob3(20,L)。L=[0,1,2,5,12,29,70,169,408,|..@user197618这是SWI Prolog用于显示输出的缩写。当收到提示时,按
w
(而不是符号,
)。请参阅。
:- use_module(library(lambda)).

f(N, FN) :-
    cont_f(N, _, FN, \_^Y^_^U^(U = Y)).

cont_f(N, FN1, FN, Pred) :-
    (   N < 2 ->
        call(Pred, 0, 1, FN1, FN)
    ;
        N1 is N - 1,
        P = \X^Y^Y^U^(U is X + 2*Y),
        cont_f(N1, FNA, FNB, P),
        call(Pred, FNA, FNB, FN1, FN)
    ).
?- time((between(0,1000,N), prob3(N,_), false)).
% 10,939 inferences, 0.011 CPU in 0.012 seconds (99% CPU, 951780 Lips)

:- dynamic memo/2.
prob3(0, 0).
prob3(1, 1).
prob3(N, R) :- memo(N, R), !.
prob3(N, R) :-
    N > 1, N2 is N-2, N1 is N-1, prob3(N2,R2), prob3(N1,R1), R is R2+2*R1, assertz(memo(N, R)).