1

最近我尝试了《在 Prolog 中构建专家系统》一书,该书可在http://www.amzi.com/ExpertSystemsInProlog免费获得。

附录中有一个名为 native shell 的代码以及一个鸟类识别数据库。问题是在咨询了shell并运行之后:

主要的。

加载。

解决。

它询问“鼻孔:external_tubular?”

如果您回答否,则会发生堆栈溢出。问题可能出在以下部分:

prove(true,_) :- !.
prove((Goal,Rest),Hist) :-
    prov(Goal,[Goal|Hist]),
    prove(Rest,Hist).
prove(Goal,Hist) :-
    prov(Goal,[Goal|Hist]).

prov(true,_) :- !.
prov(menuask(X,Y,Z),Hist) :- menuask(X,Y,Z,Hist), !.
prov(ask(X,Y),Hist) :- ask(X,Y,Hist), !.
prov(Goal,Hist) :-
    clause(Goal,Body),
    prove(Body,Hist).

有人可以请帮助我吗?非常感谢任何帮助。

shell的完整代码:http: //www.amzi.com/ExpertSystemsInProlog/code/native/native.pro

数据库的完整代码:http: //www.amzi.com/ExpertSystemsInProlog/code/native/birds.nkb

我正在使用 swi prolog。

4

3 回答 3

1

这个问题确实通过

prove(Goal,Hist) :-
    prov(Goal,[Goal|Hist]).

prov(Goal,Hist) :-
    clause(Goal,Body),
    prove(Body,Hist).

clause(:Head, ?Body)如果Head可以与子句头部和Body相应的子句主体统一,则应该为真。不幸的是,对于任何SWI-Prolog 认为clause(call(X), call(X))是真实的程序。这意味着clause(call(nostrils(external_tubular)), X)成功prove并被调用,而后者又调用prov了不断增长的第二个参数。

由于clause/2是一个静态谓词,它的内容不能用retractallor修改abolish。可能的解决方案是:

  1. 向 SWI 开发人员报告错误
  2. 在 shell 的实现中用类似和引用birds.nkb的东西替换子句。myclausemyclause
  3. 看看其他一些 Prolog 方言......
于 2012-05-27T20:45:26.850 回答
1

我发现问题出在这里:

prove((Goal,Rest),Hist) :-
    prov(Goal,[Goal|Hist]),
    prove(Rest,Hist).
prove(Goal,Hist) :-
    prov(Goal,[Goal|Hist]).

由于 swi-prolog 允许头部 ((x,y,z), [h]) 匹配第二个证明谓词,因此在推理过程中会以某种方式触发证明(Goal,Hist),这将导致无限循环发生。我花了 8 个小时来分析痕迹。

因此,为了解决这个问题,我们需要在prove((Goal,Rest),Hist) 的开头放置一个cut。代码应如下所示:

prove((Goal,Rest),Hist) :-
    !,
    prov(Goal,[Goal|Hist]),
    prove(Rest,Hist).
prove(Goal,Hist) :-
    prov(Goal,[Goal|Hist]).
于 2012-05-28T05:49:14.667 回答
0

您还可以通过在prov((_,_),_) :- !, fail.该部分正上方添加谓词来修复它:

prov(true,_) :- !.
prov(menuask(X,Y,Z),Hist) :- menuask(X,Y,Z,Hist), !.
prov(ask(X,Y),Hist) :- ask(X,Y,Hist), !.
prov(Goal,Hist) :-
    clause(Goal,Body),
    prove(Body,Hist).
于 2012-06-05T14:45:19.520 回答