Prolog 和平方根列表元素

Prolog 和平方根列表元素,prolog,Prolog,所以我现在正试图用Prolog计算一个公式。我目前已经完成了公式的一部分,但是我在实现下一部分时遇到了问题,我需要添加列表中的元素,然后求和的平方根。不知道我会怎么做 我目前拥有的: formula([], [], []). formula([], [H2|T2], [L|Ls]) :- L = H2, formula([], T2, Ls). formula([H1|T1], [], [L|Ls]) :- L = H1, formula(T1, [], Ls). formula

所以我现在正试图用Prolog计算一个公式。我目前已经完成了公式的一部分,但是我在实现下一部分时遇到了问题,我需要添加列表中的元素,然后求和的平方根。不知道我会怎么做

我目前拥有的:

formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
  L = H2,
  formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
  L = H1,
  formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
  L is (H1 - H2)*(H1 - H2),
  formula(T1, T2, Ls).

使用SWI Prolog库谓词
sum_list/2

list_summed_and_square_rooted(List, Value) :-
    sum_list(List, Sum),
    Value is sqrt(Sum).
您可能不需要编写单独的谓词来将列表与其元素之和的平方根相关联,除非您需要经常使用该特定关系。您的
公式/3
将两个列表中的一个列出来,但最终您似乎在寻找一个数值,因此您可能需要另一个谓词来描述两个列表与结果数值之间的关系

lists_processed_in_some_way(List1, List2, Value) :-
    formula(List1, List2, CombinedList),
    sum_list(CombinedList, Sum),
    Value is sqrt(Sum).

顺便说一下,你可以简化你的
公式/3
,因为你不需要
L=H2

formula([], [H2|T2], [H2|Ls]) :-
    formula([], T2, Ls).
此外,通常最好仔细命名谓词,并使用描述性的名称。它将帮助您对谓词的作用进行推理,并帮助您与其他人交流您的程序。

您的原始公式

formula([], [], []).
formula([], [H2|T2], [L|Ls]) :-
  L = H2,
  formula([], T2, Ls).
formula([H1|T1], [], [L|Ls]) :-
  L = H1,
  formula(T1, [], Ls).
formula([H1|T1], [H2|T2], [L|Ls]) :-
  L is (H1 - H2)*(H1 - H2),
  formula(T1, T2, Ls).
可以简化以使模式匹配更加明确:

formula( []     , []     , []     ) .
formula( []     , [Y|Ys] , [Y|Zs] ) :- formula( [] , Ys , Zs ) .
formula( [X|Xs] , []     , [X|Zs] ) :- formula( Xs , [] , Zs ) .
formula( [X|Xs] , [Y|Ys] , [Z|Zs] ) :-
  L is ( X - Y ) * ( X - Y ) ,
  formula(Xs,Ys,Zs)
  .
我假设您的讲师希望您在这里学习递归,而不是使用内置谓词。所以您可以这样对列表中的元素求和(天真的实现):

但是,一旦列表变得足够长,并且每次递归调用都会将一个新的帧推送到堆栈上,那么堆栈溢出就会失败。Prolog有一个漂亮的优化(尾部递归优化),它通过识别何时可以重用堆栈框架,有效地将递归转换为迭代。要做到这一点,Recrive调用必须是最后一件事

这在prolog编程中引入了一种常见模式:

  • 一个公共接口谓词(这里,
    sum\u of/2
  • 调用“私有”尾部递归工作谓词(此处为/3的sum_),该谓词使用累加器参数构建其结果
使用该模式,我们得到以下实现:

sum_of( [] , 0 ) .      % the sum of the empty list is zero.
sum_of( [X|Xs] , S ) :- % the sum of an empty list is computed by
  sum(Xs,T) ,           % - computing the sum of the tail of the list
  S is T+X              % - and adding that to the value of the head of the list.
  .                     %
 sum_of(Xs,Sum) :- sum_of(Xs,0,Sum) .

 sum_of( []     , S , S ) .  % the sum of the empty list is 0.
 sum_of( [X|Xs] , T , S ) :- % the sum of a non-empty list is computed by
   T1 is T+X ,               % incrementing the accumulator by the value of the head of the list, and
   sum_of( Xs , T1 , S )     % recursing down on the tail.
   .                         % Easy!

这适用于任何长度的列表。

对不起,我是prolog新手。我是将其插入到当前函数中,还是将其放入自己的单独函数中。@user3281114没问题。我将扩展我的答案以说明用法,但我现在没有时间。仅供参考:在Prolog中,我们使用谓词而不是函数。这不仅仅是一个技术术语问题:可以对函数进行评估并用其输出“替换”。在使用函数的语言中,我们可以编写
list\u summary\u和\u square\u root/2的主体,因此:
Value=sqrt(sum\u list(list))
。然后,
sum_list
返回的值将被传递到
sqrt
并分配给
value
。在Prolog中,除了一些显式标记的异常外,谓词仅“返回”真值。请注意,
sum\u list/2
不是标准谓词,但根据Prolog系统的不同,它可能作为库谓词可用。@user3281114终于有机会进行添加。如果你还有问题,请告诉我!改为写入
L为(H1-H2)^2