Control 版 (精华区)
发信人: dagam (断情), 信区: Control
标 题: [转载]专家系统解释[3]
发信站: 哈工大紫丁香 (2001年07月01日11:50:27 星期天), 站内信件
上面就是完整的how的编写过程了。不过它只显示出直接推导出某个规则,而这些规则
又是基于其他的规则或者事实的,如何进一步的推理信息呢?有两种方法:
让用户使用how继续询问,
让how命令自动的显示完整的证明树。
第一项功能已经实现,如何实现第二个功能呢?我们使用how_lhs把rulelist中的每个规
则作为目标,递归的调用how。当某个目标的rulelist为空的时候,表示这个目标不是由
规则得出的,而是用户输入的已知事实,这就是说完成了整个证明树的搜索过程。
list_rules([]).
list_rules([R|X]) :-
list_rule(R),
how_lhs(R),
list_rules(X).
how_lhs(N) :-
rule(N, lhs(Iflist), _),
!,
how_ifs(Iflist).
how_ifs([]).
how_ifs([Goal|X]) :-
how(Goal), how_ifs(X).
在这里我们回答how提问有3种选择:只显示规则名,显示规则的内容,显示完整的搜索
树。
回答why提问
当系统得出某个结论之后,用户可以使用how向它询问是如何得出这个结论的。而在系统
的用户的对话过程中,系统为了收集资料会向用户询问,这个时候如果用户感到困惑的
时候,可以询问系统为什么问这个问题。
为了回答why问题,我们需要跟踪推理过程,也就是说要记录下以前推理一些信息。在推
理谓词中增加一个保存这种信息的参数,就可以很好的解决这个问题。在findgoal和pr
ove中我们增加了一个Hist参数。
findgoal(Goal, CurCF, Hist) :-
fg(Goal, CurCF, Hist).
fg(Goal, CurCF, Hist) :-
...
prove(N, IfList, Tally, Hist),
...
在prove谓词中,在递归调用findgoal去寻找进一步的解的前面,先把现在所使用的规则
记录下来。
prove(N, IfList, Tally, Hist) :-
prov(IfList, 100, Tally, [N|Hist]), !.
prove(N, _, _) :-
bugdisp(['fail rule', N]),
fail.
prov([], Tally, Tally, Hist).
prov([H|T], CurTal, Tally, Hist) :-
findgoal(H, CF, Hist),
min(CurTal, CF, Tal),
Tal >= 20,
prov(T, Tal, Tally, Hist).
我们举个例子说明一下,当系统需要证明a的时候,它发现要使用b,c。当它开始着手证
明b之前,先把a记录下来,这样当用户询问系统你为什么要证明b的时候,它就可以告诉
用户:我是要证明a才来证明b的。假如证明b又需要d和e,在在证明d和e之前,先把b记
录下来,而d和e是需要向用户收集的信息,用户可能会询问为什么要问我d和e这样的问
题,这时系统中的历史列表应该是[b,a],系统查询这个列表就会告诉用户,我需要证
明b,因此询问d和e,而用户问为什么要证明b呢,系统就会回答是要证明a。显然有了这
个历史列表,系统就知道自己为什么要获得某个属性的值了。
由于why命令是用户在和系统的对话的中间询问的,和原来how命令有些不同。原来的外
壳命令help、exit、how等等,都不能在对话中间使用,下面我们就修改原来的程序,让
用户可以打断和系统的对话,来做其他的事情。用下面的get_user谓词替代以前的向用
户询问的谓词,这个get_user谓词允许在对话中间运行why,trace,help命令,当然加
入其他的命令也是不困难的。
get_user(X, Hist) :-
repeat,
write(': '),
read_line(X),
process_ans(X, Hist).
process_ans([why], Hist) :- nl, write_hist(Hist), !, fail.
process_ans([trace, X], _) :- set_trace(X), !, fail.
process_ans([help], _) :- help, !, fail.
process_ans(X, _). % just return user's answer
write_hist([]) :- nl.
write_hist([goal(X)|T]) :-
write_line([goal, X]),
!, write_hist(T).
write_hist([N|T]) :-
list_rule(N), !,
write_hist(T).
在回答why的时候,不仅仅显示规则名,还可以显示规则的内容。
在原始的推理引擎中加入解释
还记得第一章介绍的那个识别鸟类的专家系统么,由于这个专家系统使用的是prolog的
推理引擎,所以无法加入解释功能,为了加入解释,我们必须使用prolog编写一个prol
og解释器,这项工作很容易完成。当编写完成了自己的推理引擎之后,就可以很方便的
处理解释了。
推理引擎首先要能够读取规则,在prolog中,子句本身就是prolog的项。内部谓词clau
se可以让我们存取规则。它的两个参数分别与子句的头和内容匹配。事实的内容就只有
目标ture一个。
还记得第一章介绍的那个识别鸟类的专家系痛硬幌 欢光光一个,可惜偏偏光光一个og的
推理引擎,所以无法加入解释功能,为了加入解释,我们必须使用prolog编写一个prol
og解释器,这项工作很容易完成。当编写完成了自己的推理引擎之后,就可以很方便的
处理解释了。
推理引擎首先要能够读取规则,在prolog中,子句本身就是prolog的项。内部谓词clau
se可以让我们存取规则。它的两个参数分别与子句的头和内容匹配。事实的内容就只有
目标ture一个。
在prolog的语法中,使用“,”隔开规则的每个子目标,其实在prolog中,规则的储存
方法和我们看上去的有很大的不同。下面我们举个例子。
对于规则a:-b,c,d.在prolog中的实际结构是:-(a,&(b,&(c,d))).可以看出,这和我们自
己定义的数据结构信息是相同的。例如我们可能会定义:father(a,b).在这里father就
是谓词,a和b就是参数。而在规则中,:-是谓词,&也是谓词。这一点在前面的prolog语
言介绍中过。
--
--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: heart.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.226毫秒