Пролог и "обратный" вывод в экспертной системе
Я новичок в Прологе. Я сумел понять, как сделать простую экспертную систему, как
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.
И это хорошо, но вопрос в том, как сделать вывод "назад", например, я напечатаю "танк" в окне пролога, и он даст все детали, из которых состоят эти танки - например, пистолет - да, короткая винтовка - да, крылья - нет и т. д.
Это возможно сделать в экспертной системе, как это, или я должен сделать другую программу?
Спасибо за ваш ответ
1 ответ
Поскольку ваши пункты просты, я думаю, что вы могли бы сделать это с помощью 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
позволяет проверять правила Пролога программно. Это механизм отражения. clause(Head, Body)
объединяет Главу с именем правила и Тело с его телом - другими словами, Head :- Body
, Поэтому, когда мы говорим, clause(tank, Body)
мы вернемся:
Body = (grounder, verify(has_gun), verify(short_fire)).
Разложение это несколько обременительно; в конце концов, вы должны пересечь столько же самого Пролога, сколько используете в своих правилах. Но это то, что делает остальная часть кода. Во-первых, мы получаем пункт в part/2
: обратите внимание, что тип, который я ожидаю для Part, - это тип атома транспортного средства. Как только мы получим предложение, мы передадим его part_of_body для декомпозиции структуры Пролога.
Отсюда базовый случай будет что-то вроде 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.
Таким образом, эта база данных может работать в обратном направлении, это просто не очень удобно.:) Лучшая модель данных будет иметь большое значение для улучшения этой ситуации.