Листинг

Раздел описания доменов является аналогом раздела описания типов в обычных императивных языках программирования и начинается с ключевого слова 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.