首页 > 解决方案 > 我想使用 Prolog 来订购一些东西,但我不断收到堆栈溢出错误

问题描述

在我的物理课上,我们在赛道上进行各种滚动比赛,并试图找出是什么让最快的东西最快。

我想节省时间,而不是与一切竞争。例如,一罐鸡汤胜过一罐蛤蜊,一罐蛤蜊胜过一罐西红柿。所以,鸡汤一定要打败西红柿。

这是我到目前为止写的所有内容:

% Define everything we know
outspeeds(chicken_soup, clams). % This represents "chicken_soup outspeeds clams."
outspeeds(beef, clams).
outspeeds(chicken_soup, beef).
outspeeds(chicken_soup, tomatoes).
outspeeds(clams, tomatoes).

% Now define inter-relationships
% A outspeeds B if A outspeeds some 3rd party "X" and they outspeed B.
outspeeds(A, B) :- outspeeds(A, X), outspeeds(X, B).

问题是当我尝试询问有关它的问题时。如果我试图找到所有chicken_soup超速的东西,会发生以下情况:

?- outspeeds(chicken_soup, X).
X = clams ;
X = beef ;
X = tomatoes ;
X = tomatoes ;
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 1.0Gb, global: 4Kb, trail: 0Kb
ERROR:   Stack depth: 12,197,875, last-call: 0%, Choice points: 5
ERROR:   Probable infinite recursion (cycle):
ERROR:     [12,197,875] user:outspeeds(tomatoes, _1098)
ERROR:     [12,197,874] user:outspeeds(tomatoes, _1118)

为什么要这样做?最后我需要什么附加条款outspeeds来防止堆栈溢出?

我是 Prolog 的新手,所以如果整个项目有什么可怕的问题,请告诉我。

标签: prologstack-overflow

解决方案


卡尔文,你确定这是给物理课的吗?”

但也许这会有所帮助:

西红柿什么也没有

Wirth 教授让我终身讨厌调试器,我喜欢打印输出语句:

outspeeds_s(chicken_soup, clams, Sd, Sd)    :- format("Fact: outspeeds(~w, ~w)\n",[chicken_soup,clams]).
outspeeds_s(beef, clams, Sd, Sd)            :- format("Fact: outspeeds(~w, ~w)\n",[beef,clams]).
outspeeds_s(chicken_soup, beef, Sd, Sd)     :- format("Fact: outspeeds(~w, ~w)\n",[chicken_soup,beef]).
outspeeds_s(chicken_soup, tomatoes, Sd, Sd) :- format("Fact: outspeeds(~w, ~w)\n",[chicken_soup,tomatoes]).
outspeeds_s(clams, tomatoes, Sd, Sd)        :- format("Fact: outspeeds(~w, ~w)\n",[clams,tomatoes]).

outspeeds_s(A, B, Sd_in, Sd_max) :- 
    format("Stack ~w: The question is outspeeds(~w, ~w)?\n",[Sd_in,A,B]),
    format("Stack ~w: ~w is fresh variable, we will now try outspeeds(~w, ~w)?\n",[Sd_in,X,A,X]),
    Sd_next is Sd_in+1,
    % can't ask the user in SWISH, so we sleep 3 seconds instead
    sleep(3),
    outspeeds_s(A, X, Sd_next, Sd_max_1),
    format("Stack ~w: We found that outspeeds(~w, ~w)!\n",[Sd_in,A,X]),
    format("Stack ~w: But does outspeeds(~w, ~w)?\n",[Sd_in,X,B]),
    % can't ask the user in SWISH, so we sleep 3 seconds instead
    sleep(3),       
    outspeeds_s(X, B, Sd_next, Sd_max_2),
    Sd_max is max(Sd_max_1, Sd_max_2),
    format("Stack ~w: We also found that outspeeds(~w, ~w)!\n",[Sd_in,X,B]),
    format("Stack ~w: So we can conclude that outspeeds(~w, ~w)!\n",[Sd_in,A,B]).

outspeeds(X,Y) :-
    format("outspeeds(~w, ~w)?\n",[X,Y]),
    outspeeds_s(X,Y,0,Ss_max),
    format("Found that outspeeds(~w, ~w) with max stack depth ~w\n",[X,Y,Ss_max]).

您可以区分无限递归要求outspeeds(tomatoes,_)

在SWISH中尝试一下。

(遗憾的是,SWISH 不接受用户通过 输入get/1,这需要添加。)

为了实际解决问题,您可以选择几种方法来使潜在的绊雷outspeeds(A, B) :- outspeeds(A, X), outspeeds(X, B).无害。阅读这个最近的问题以获得一两个想法:

需要递归循环退出语句


推荐阅读