Как остановить программу в Прологе, если достигнуто условие? - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь построить простую экспертную систему в прологе. У меня есть следующий код:

% Data about bands
band(megadeth):- music(vocal),vocals(male),
    genre(rock),sub_genre(heavy_metal),subsub_genre(thrash),activity(active),nr_members(4).
band(pantera):- music(vocal),vocals(male),
    genre(rock),sub_genre(heavy_metal),subsub_genre(groove),activity(disbanded),nr_members(4).
band(dio):- music(vocal),vocals(male),
    genre(rock),sub_genre(heavy_metal),activity(disbanded),nr_members(5).
band(ewf):- music(vocal),vocals(male),
    genre(pop),sub_genre(dance_pop),activity(active),nr_members(8).
band(dethklok):- music(vocal),vocals(male),genre(rock),sub_genre(heavy_metal),
    subsub_genre(death_metal),activity(disbanded),nr_members(5).
band(nightwish):- music(vocal),vocals(female),genre(rock),
    sub_genre(heavy_metal),subsub_genre(power_metal),activity(active),nr_members(6).
band(animals_as_leaders):- music(instrumental),genre(rock),sub_genre(heavy_metal),
    subsub_genre(progressive_metal),activity(active),nr_members(3).


% Asks

music(X):- menuask(music,X,[vocal,instrumental]).
vocals(X):- menuask(vocals,X,[male,female]).
genre(X):- menuask(genre,X,[rock,pop]).
sub_genre(X):- menuask(sub_genre,X,[heavy_metal,dance_pop]).
subsub_genre(X):- menuask(subsub_genre,X,[thrash,groove,death_metal,
                                           power_metal,progressive_metal]).
activity(X):- menuask(activity,X,[active,disbanded]).
nr_members(X):- menuask(nr_members,X,[3,4,5,8]).


:- dynamic(known/3).
:- discontiguous menuask/3.
:- discontiguous ask/2.

% Remember what I've been told is correct
ask(Attr, Val) :- known(yes, Attr, Val), !.
menuask(Attr, Val, _) :- known(yes, Attr, Val), !.
% Remember what I've been told is wrong
ask(Attr, Val) :- known(_, Attr, Val), !, fail.
menuask(Attr, Val, _) :- known(_, Attr, Val), !, fail.
% Remember when I've been told an attribute has a different value
ask(Attr, Val) :- known(yes, Attr, V), V \== Val, !, fail.
menuask(Attr, Val, _) :- known(yes, Attr, V), V \== Val, !, fail.
% % I don't know this, better ask!
ask(Attr, Val) :- write(Attr:Val), write('? '),
                           read(Ans),
                           asserta(known(Ans, Attr, Val)), Ans == yes.
menuask(Attr, Val, List) :-
                            write('What is the value for '), write(Attr), write('? '), nl,
                            write(List), nl,
                            read(Ans),
                            check_val(Ans, Attr, Val, List),
                            asserta(known(yes, Attr, Ans)),
                            Ans == Val.
check_val(Ans, _, _, List) :- member(Ans, List), !.
check_val(Ans, Attr, Val, List) :-
                            write(Ans), write(' is not a known answer, please try again.'), nl,
                            menuask(Attr, Val, List).

go :- band(Band), write('I will suggest you the following band(s): '), write(Band), nl.

Итак, я хочу, чтобы программа немедленно дала ответ, если, например, я выберу в первый вопрос «инструментальный», который уникален для животных как лидеров. Мне не нужна программа, чтобы задавать дополнительные вопросы. Кроме того, как я могу сделать так, чтобы программа давала два или более ответов, потому что многие группы имеют одинаковые характеристики, если представлены в моей простой экспертной системе.

...