使用Prolog中的累加器评估多项式的​​评估问题

时间:2013-03-06 22:10:38

标签: prolog polynomial-math accumulator

背景

我需要写一个谓词eval(P,A,R),其中:
P表示多项式系数的列表,即1 + 2x + 3x ^ 2表示为[1,2,3] A代表X的值 R是X = A处的多项式的结果。

例子: eval([3,1,2],3,R)产生R = 24. *编辑,以前不正确的例子

我正试图在Learn Prolog Now上使用本文和示例中的累加器。

我的算法:
0.将结果和指数变量初始化为0 1.取名单的头部 2.将列表的头部乘以A ^(指数) 3.更新结果和指数。

我的代码:

eval(P,A,R) :- accEval(P,A,0,0,R).      
accEval(([H|T]),A,Pow,Accres,R) :- 
        Rnew is (Accres+H*(A**Pow)), 
        Pownew is Pow+1, 
        R = Accres, 
        accEval(T,A,Pownew,Rnew,Rnew).  % *See below
accEval([],A,Pow,Accres,Accres).

% *Previously, when the second Rnew in this line was R instead, output was "no".

生成跟踪:

| ?- eval([1,2],3,R).
  1    1  Call: eval([1,2],3,_20) ? 
  2    2  Call: accEval([1,2],3,0,0,_20) ? 
  3    3  Call: _126 is 0+1*3**0 ? 
  3    3  Exit: 1.0 is 0+1*3**0 ? 
  4    3  Call: _157 is 0+1 ? 
  4    3  Exit: 1 is 0+1 ? 
  5    3  Call: accEval([2],3,1,1.0,1.0) ? 
  6    4  Call: _218 is 1.0+2*3**1 ? 
  6    4  Exit: 7.0 is 1.0+2*3**1 ? 
  7    4  Call: _249 is 1+1 ? 
  7    4  Exit: 2 is 1+1 ? 
  8    4  Call: accEval([],3,2,7.0,7.0) ? 
  8    4  Exit: accEval([],3,2,7.0,7.0) ?  % We have the correct answer.
  5    3  Exit: accEval([2],3,1,1.0,1.0) ? % Wait! What are you doing!?
  2    2  Exit: accEval([1,2],3,0,0,0) ?   % Why is this falling back out?
  1    1  Exit: eval([1,2],3,0) ? 

R = 0  % Incorrect. The answer should be 7.

正如我的代码所述,先前的尝试没有为R产生任何价值,而是产生“否”或在其他实施中产生“是”。

问题

为什么结果丢失而没有带回原来的电话?

3 个答案:

答案 0 :(得分:2)

它有点简单:

eval(P,A,R) :- accEval(P,A,0,0,R).
accEval(([H|T]),A,Pow,Accres,R) :-
        Rnew is (Accres+H*(A**Pow)),
        Pownew is Pow+1,
        accEval(T,A,Pownew,Rnew,R).  % *See below
accEval([],_A,_Pow,Accres,Accres).

但您的示例似乎不正确

?-  eval([3,2,1],3,R).
R = 18.

并且实际上3 + 2 * X + X ^ 2,其中X = 3,产生18 p

答案 1 :(得分:1)

应该在递归结束时与累加器值统一的变量已经绑定到一个值。使用累加器的方式如下:

  • 在您第一次打电话时给累加器一个初始值"谓词
  • 使用累加器将累计值传递给递归调用
  • 将结果与递归结束条款中的累加器统一起来

根据经验,谓词头部的Result变量是传递给递归调用的相同变量。这样,一旦它与最后的实际结果统一(在递归结束子句中),它也将被递送出递归到调用者。

答案 2 :(得分:0)

这里的策略可能是所谓的Horner架构。在Horner模式中,您不需要幂函数(**)/ 2或(^)/ 2。 Horner schema说:

a_0 + a_1*x + .. + a_n-1*x^n-1 + a_n*x^n =

a_0 + x*(a_1 + .. + x*(a_n-1 + x*a_n)..)

如果允许以相反的顺序[a_n,..,a_0]提供系数,Horner模式很容易在Prolog中实现,如下所示:

eval([C|L], X, R) :-
    eval(L, C, X, R).

eval([C|L], A, X, R) :-
    B is A*X+C,
    eval(L, B, X, R).
eval([], A, _, A).

作为奖励,霍纳计划在数值上更加稳定。以下是一个示例运行:

?- eval([2,1,3],3,R).
R = 24