我是Prolog的新手。我习惯了解如何做简单的专家系统,比如
go :- hypothesize(Vehicle),
write('I guess that the Vehicle is: '),
write(Vehicle), nl, undo.
hypothesize(car) :- car, !.
hypothesize(van) :- van,!.
hypothesize(bike) :- bike, !.
hypothesize(mini) :- mini, !.
hypothesize(tank) :-tank, !.
hypothesize(sau) :- sau, !.
hypothesize(excavator) :- excavator, !.
hypothesize(bulldozer) :- bulldozer, !.
hypothesize(rocket) :- rocket, !.
hypothesize(shuttle) :- shuttle , !.
hypothesize(destroyer) :- destroyer, !.
hypothesize(civil_plane) :- civil_plane, !.
hypothesize(unknown).
/* Vehicle identification rules */
sau :- grounder,
verify(has_gun),
verify(long_fire).
tank :- grounder,
verify(has_gun),
verify(short_fire).
excavator :- grounder,
verify(no_gun),
verify(have_ladle).
bulldozer :- grounder,
verify(no_gun),
verify(no_ladle).
car :- grounder,
verify(big_body),
verify(for_passengers).
van :- grounder,
verify(big_body),
verify(for_cargo).
bike :- grounder,
verify(small_body),
verify(two_wheels).
mini :- grounder,
verify(small_body),
verify(four_wheels).
rocket :- flying,
verify(cosmos_flying),
verify(can_return).
shuttle :- flying,
verify(cosmos_flying),
verify(cant_return).
destroyer :- flying,
verify(air_flying),
verify(warmade).
civil_plane :- flying,
verify(air_flying),
verify(civil).
/* classification rules */
grounder :- verify(has_wheels), !.
grounder :- verify(have_engine).
flying :- verify(has_wings), !.
flying :- verify(has_jets).
/* how to ask questions */
ask(Question) :-
write('Does the vehicle have the following attribute: '),
write(Question), write('? '),
read(Response), nl,
( (Response == yes ; Response == y)
-> assert(yes(Question)) ;
assert(no(Question)), fail).
:- dynamic yes/1,no/1.
/* How to verify something */
verify(S) :- (yes(S) -> true ; (no(S) -> fail ; ask(S))).
/* undo all yes/no assertions */
undo :- retract(yes(_)),fail.
undo :- retract(no(_)),fail.
undo.
这很好,但问题是 - 怎么做“后退”输出,比如,我会在prolog窗口输入“tank”,他会给这个坦克组成的所有部分 - 比如,枪 - 是的,短步枪 - 是的,翅膀 - 不,等等
是否可以在这样的专家系统中进行,或者我必须做另一个程序?
感谢您的回复
答案 0 :(得分:2)
因为您的条款很简单,我认为您可以使用clause/2
这样做:
?- clause(grounder, X).
X = (verify(has_wheels), !) ;
X = verify(have_engine).
这看起来像这样:
part(Vehicle, Part) :-
clause(Vehicle, Body),
part_of_body(Body, Part).
part_of_body(verify(Part), Part).
part_of_body(X, Part) :-
atom(X), X \= '!', part(X, Part).
part_of_body((X,Y), Part) :-
part_of_body(X, Part)
; part_of_body(Y, Part).
这是一个元解释器。 clause/2
允许您以编程方式检查Prolog的规则。它是一种反思机制。 clause(Head, Body)
将Head与规则的名称和Body与其正文统一起来 - 换句话说,Head :- Body
。所以,当我们说clause(tank, Body)
时,我们会回来:
Body = (grounder, verify(has_gun), verify(short_fire)).
分解这有点麻烦;毕竟,你必须像你在规则中那样遍历Prolog本身。但这就是其余代码所做的事情。首先,我们在part/2
中获取子句:请注意,我期望Part的类型是车型原子的类型。一旦我们获取该子句,我们将其交给part_of_body来分解Prolog的结构。
从这里开始,基本情况类似于verify(has_gun)
,它似乎包含您感兴趣的作品(has_gun
)以及规则{{ 1}}说。
递归情况是处理结构其余部分的情况,例如,如果我看到part_of_body(verify(Part), Part)
之类的原子,我会递归查找那些部分,这就是grounder
所做的。我不必为part_of_body(X, Part)
进行专门测试而感到兴奋,但我的方法存在一个无法修复的问题。
主递归案例是处理连词的案例:!
。在这里我只是说,在连接的第一部分找到一些部分,然后尝试第二部分。
(X,Y)
因此,这个数据库可以向后工作,它不是特别方便。 :)一个更好的数据模型将大大改善这种情况。