微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有列表的 Prolog 基本练习给出了堆栈大小错误

如何解决带有列表的 Prolog 基本练习给出了堆栈大小错误

我开始学习 prolog,但我被这个问题困住了,如果有人能告诉我我做错了什么以及为什么错了,这将非常有帮助,这样我就可以学习了。

锻炼

编写一个遵循以下语法的谓词:

supr_bigger(Elem,List,Result)

其中 Result 是列表 List,但删除了所有大于 Elem 的元素。

代码

supr_bigger(_,[],[]).

supr_bigger(Elem,[X|Y],R) :- X =< Elem,insert(X,R,R1),supr_bigger(Elem,Y,R1).

supr_bigger(Elem,R) :- X > Elem,R).



insert(Z,L1,L2) :- choose(Z,L2,L1).


choose(X,[X|L],L).
choose(X,[Y|L1],[Y|L2]) :- choose(X,L2).

当我尝试测试上面的代码时,出现此错误
?- supr_bigger(3,[3,2,5,4,1,6],R)。

错误:超出堆栈限制 (1,0Gb)
错误:堆栈大小:本地:2Kb,全局:0,9Gb,轨迹:0Kb
错误:堆栈深度:16,最后调用:13%,选择点:11

非常感谢。

解决方法

您可以使用谓词 trace/1 找出您的代码有什么问题:

?- trace,supr_bigger(3,[3,2,1,4],R).
   Call: (11) supr_bigger(3,_4526) ? creep
   Call: (12) 3=<3 ? creep
   Exit: (12) 3=<3 ? creep
   Call: (12) insert(3,_4526,_5168) ? creep
   Call: (13) choose(3,_5210,_4526) ? creep
   Exit: (13) choose(3,[3|_4526],_4526) ? creep
   Exit: (12) insert(3,[3|_4526]) ? creep
   Call: (12) supr_bigger(3,[2,[3|_4526]) ? creep
   Call: (13) 2=<3 ? creep
   Exit: (13) 2=<3 ? creep
   Call: (13) insert(2,_5482) ? creep
   Call: (14) choose(2,_5524,[3|_4526]) ? creep
   Exit: (14) choose(2,3|_4526],[3|_4526]) ? creep
   Exit: (13) insert(2,3|_4526]) ? creep
   Call: (13) supr_bigger(3,[1,3|_4526]) ? creep
   Call: (14) 1=<3 ? creep
   Exit: (14) 1=<3 ? creep
   Call: (14) insert(1,_5796) ? creep
   Call: (15) choose(1,_5838,3|_4526]) ? creep
   Exit: (15) choose(1,3|_4526]) ? creep
   Exit: (14) insert(1,3|_4526]) ? creep
   Call: (14) supr_bigger(3,[4],3|_4526]) ? creep
   Call: (15) 4=<3 ? creep
   Fail: (15) 4=<3 ? creep
   Redo: (14) supr_bigger(3,3|_4526]) ? creep
   Call: (15) 4>3 ? creep
   Exit: (15) 4>3 ? creep
   Call: (15) supr_bigger(3,[],3|_4526]) ? creep
   Fail: (15) supr_bigger(3,3|_4526]) ? 

如您所见,当输入列表为(调用 15)时,输出列表实际上包含所有应该被选中的元素。但是,supr_bigger/3 不能 的递归定义中的base 子句 不能用于这种情况,因为列表 [](子句的第三个参数)和 { {1}}(目标的第三个参数)不匹配。

要解决问题,您可以将代码修改为:

  • 关闭打开列表 [1,3|_4526],将其转换为 [1,3|_4526]
  • 添加新参数以收集最终结果。

但是,由于您的代码还有许多其他问题,最好尝试更简单的方法

[1,3]

示例:

supr_bigger(_,[]).
supr_bigger(B,[X|Xs],[X|Ys]) :- X =< B,supr_bigger(B,Xs,Ys).
supr_bigger(B,Ys) :- X  > B,Ys).

消除虚假选择点,您可以执行以下操作

?- supr_bigger(3,R).
R = [3,1] ;
false.

示例:

supr_bigger(B,L,R) :-
    best_supr_bigger(L,B,R).

best_supr_bigger([],_,[]).
best_supr_bigger([X|Xs],R) :-
    (   X =< B
    ->  R = [X|Ys]
    ;   R = Ys ),best_supr_bigger(Xs,Ys).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。