2

我是 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. 

这很好,但问题是 - 如何进行“后退”输出,例如,我将在序言窗口中输入“坦克”,他将给出这个坦克的所有部件 - 比如枪 - 是的,短步枪 -是的,翅膀 - 不,等等

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

感谢你的回复

4

1 回答 1

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 类型是车辆类型 atom 的类型。一旦我们获取了子句,我们就将它交给 part_of_body 来分解 Prolog 的结构。

从这里开始,基本案例将类似于verify(has_gun),它似乎包括您感兴趣的部分 ( has_gun),这就是规则part_of_body(verify(Part), Part)所说的。

递归情况是处理结构其余部分的情况,因此,例如,如果我看到一个原子,例如grounder,我会递归查找这些部分,这就是这样part_of_body(X, Part)做的。我对必须专门进行测试并不感到兴奋,!但我的方法有一个弱点,我还没有修复。

主要的递归案例是处理连词的案例:(X,Y). 这里我只是说,在连词的第一部分中找到一些部分,然后尝试第二部分。

?- part(tank, Part).
Part = has_wheels ;
Part = have_engine ;
Part = has_gun ;
Part = short_fire.

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

于 2015-12-01T02:38:06.747 回答