Листинг
Раздел описания доменов является аналогом раздела описания типов в обычных императивных языках программирования и начинается с ключевого слова DOMAINS:
DOMAINS
CONDITIONS = BNO *
HISTORY = RNO *
RNO, BNO, FNO = INTEGER
CATEGORY = SYMBOL
Начинается раздел описания предикатов внутренней базы данных с зарезервированного слова DATABASE и описываются в нем те предикаты, которые можно в процессе выполнения программы добавлять во внутреннюю базу данных или удалять оттуда:
DATABASE
rule(RNO, CATEGORY, CATEGORY,CONDITIONS)
cond(BNO, STRING)
yes(BNO)
no(BNO)
topic(string)
В разделе, озаглавленном зарезервированным словом PREDICATES, содержатся описания определяемых пользователем предикатов. В традиционных языках программирования подобными разделами являются разделы описания заголовков процедур и функций. Домены аргументов должны быть либо стандартными, либо объявленными в разделе описания доменов. Один предикат может иметь несколько описаний. Это используется, когда нам нужно, чтобы предикат работал с аргументами различной природы.
PREDICATES
do_expert_job
show_menu
do_consulting
process(integer)
info(CATEGORY)
goes(CATEGORY)
listopt
erase
clear
eval_reply(char)
go(HISTORY, CATEGORY)
check(RNO, HISTORY, CONDITIONS)
notes(BNO)
inpo(HISTORY, RNO, BNO, STRING)
do_answer(HISTORY, RNO, STRING, BNO, INTEGER)
goal
do_expert_job.
Все предикаты, которые применяются в этом разделе и не являются стандартными предикатами, должны быть описаны в разделе описания предикатов или в разделе описания предикатов базы данных. Начинается этот раздел со служебного слова CLAUSES.
Предложения, у которых в заголовке указан один и тот же предикат, должны идти друг за другом. Такой набор предложений называется процедурой. Программу на Прологе принято оформлять по следующим правилам:
- между процедурами пропускается пустая строка;
- тело правила записывается со следующей строки, после строки, в которой был заголовок, с отступом;
- каждую подцель записывают на отдельной строке, одну под другой.
Эти правила не являются обязательными, но они делают программу более "читабельной":
CLAUSES
topic("dog").
topic("short-haired dog").
topic("long-haired dog").
rule(1, "dog", "short-haired dog", [1] ).
rule(2, "dog", "long-haired dog", [2] ).
rule(3, "short-haired dog","English Bulldog ", [3,5,7] ).
rule(4, "short-haired dog","Beagle", [3,6,7] ).
rule(5, "short-haired dog","Great Dane", [5,6,7,8] ).
rule(6, "short-haired dog","American Foxhound",[4,6,7] ).
rule(7, "long-haired dog", "Cocker Spaniel", [3,5,6,7] ).
rule(8, "long-haired dog", "Irish Setter", [4,6] ).
rule(9, "long-haired dog", "Collie", [4,5,7] ).
rule(9, "long-haired dog", "St. Bernard", [5,7,8] ).
cond(1, "short-haired" ).
cond(2, "long-haired" ).
cond(3, "height under 22 inches" ).
cond(4, "height under 30 inches" ).
cond(5, "low-set tail" ).
cond(6, "longer ears" ).
cond(7, "good natured personality" ).
cond(8, "weight over 100 lb" ).
do_expert_job :-
makewindow(1,7,7," DOG EXPERT SYSTEM ",0,0,25,80),
show_menu,
nl,write(" Press space bar. "),
readchar(_), exit.
show_menu :-
write(" "),nl,
write(" * * * * * * * * * * * * * * * * * * "),nl,
write(" * DOG EXPERT * "),nl,
write(" * * "),nl,
write(" * 1. Consultation * "),nl,
write(" * 2. Exit the system * "),nl,
write(" * * "),nl,
write(" * * * * * * * * * * * * * * * * * * "),nl,
write(" "),nl,
write("Please enter your choice: 1 or 2 : "),nl,
readint(Choice),
process (Choice).
process(1) :- do_consulting.
process(2) :-
removewindow, exit.
do_consulting :-
goes(Mygoal), go([],Mygoal), !.
do_consulting :-
nl, write(" Sorry I can't help you."), clear.
do_consulting.
goes(Mygoal) :-
clear, clearwindow,
nl,nl, write(" "),nl,
write(" WELCOME TO THE DOG EXPERT SYSTEM "),nl,
write(" "),nl,
write("This is a dog identification system. "),nl,
write("To begin the process of choosing a "),nl,
write("dog, please type in 'dog'. If you "),nl,
write("wish to see the dog types, please "),nl,
write("type in a question mark (?). "),nl,
write(" "),nl,
readln(Mygoal), info(Mygoal),!.
info("?") :-
clearwindow, write("Reply from the KBS."),nl,
listopt, nl,write("Please any key. "),
readchar(_), clearwindow,
exit.
info(X) :- X >< "?".
listopt :-
write("The dog types are : "),nl,nl, topic(Dog),
write(" ",Dog),nl, fail.
listopt.
inpo(HISTORY,RNO,BNO,TEXT) :-
write("Question :- ",TEXT," ? "),
makewindow(2,7,7,"Response",10,54,7,20),
write("Type 1 for 'yes' ,"),nl,
write("Type 2 for 'no' : "),nl,
readint(RESPONSE), clearwindow,
shiftwindow(1),
do_answer(HISTORY,RNO,TEXT,BNO,RESPONSE).
eval_reply('y') :-
write(" I hope you have found this helpful !").
eval_reply('n') :-
write(" I am sorry I can't help you !").
go(_,Mygoal) :-
not(rule(_,Mygoal,_,_)),!,
nl,write(" The dog you have indicated is a(n) ",
Mygoal,"."),nl,
write("Is a dog you would like to have (y/n) ?"),
nl,readchar(R),
eval_reply(R).
go(HISTORY, Mygoal) :-
rule(RNO,Mygoal,NY,COND),
check(RNO,HISTORY,COND),
go([RNO|HISTORY],NY).
check(RNO,HISTORY,[BNO|REST]) :-
yes(BNO),!,
check(RNO,HISTORY,REST).
check(_,_,[BNO|_]) :- no(BNO),!,fail.
check(RNO,HISTORY,[BNO|REST]) :-
cond(BNO,NCOND),
fronttoken(NCOND,"not",COND),
frontchar(COND,_,COND),
cond(BNO1,COND),
notes(BNO1),!,
check(RNO,HISTORY,REST).
check(_,_,[BNO|_]) :-
cond(BNO,NCOND),
fronttoken(NCOND,"not",COND),
frontchar(COND,_,COND),
cond(BNO1,COND),
yes(BNO1),
!,fail.
check(RNO,HISTORY,[BNO|REST]) :-
cond(BNO,TEXT),
inpo(HISTORY,RNO,BNO,TEXT),
check(RNO,HISTORY,REST).
check(_,_,[]).
notes(BNO) :- no(BNO),!.
notes(BNO) :- not(yes(BNO)),!.
do_answer(_,_,_,_,0) :- exit.
do_answer(_,_,_,BNO,1) :-
assert(yes(BNO)),
shiftwindow(1),
write(yes),nl.
do_answer(_,_,_,BNO,2) :-
assert(no(BNO)), write(no),nl, fail.
erase :- retract(_),fail.
erase.
clear :- retract(yes(_)),retract(no(_)),fail,!.
clear.