Prolog和专家系统中的“反向”输出

时间:2015-11-29 21:11:30

标签: prolog expert-system prolog-assert

我是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”,他会给这个坦克组成的所有部分 - 比如,枪 - 是的,短步枪 - 是的,翅膀 - 不,等等

是否可以在这样的专家系统中进行,或者我必须做另一个程序?

感谢您的回复

1 个答案:

答案 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)

因此,这个数据库可以向后工作,它不是特别方便。 :)一个更好的数据模型将大大改善这种情况。