Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Авдеев, Ездаков. Лабы по ИС и ЭС.pdf
Скачиваний:
6
Добавлен:
28.06.2024
Размер:
1.57 Mб
Скачать

Приложение 2. Краткое руководство по применению языка Турбо-пролог версии 2.0

1.Имя состоит из букв, цифр и знака подчеркивания.

2.Константы могут быть одного из шести типов:

Char - символ в одиночных апострофах: ‘f’, ‘/13’, ‘B’, ‘#’, ‘%’

Integer - целое со знаком из диапазона от –32768 до 32767: –63, 84, 32763

Real - вещественное со знаком из диапазона от +/–1е–307 до

+/–1е +308:

–42769, 86.72, –521е238, 5.1е–9, –79.83е+21 Integer может автоматически переводиться в Real

String - строка, представляющая последовательность символов в двойных апострофах: "123", "today", "Ау"

Symbol - последовательность букв, цифр и подчерков, где впереди строчная буква либо строка: pay_check, flower, "railway_ticket", "Был сильный мороз"

File - файлы с именем в DOS: mail.txt, BIRDS.DBA

Данные типа symbol, в отличие от данных типа string, находятся в таблице символов, которая располагается в оперативной памяти. Поэтому использование данных типа symbol ускоряет работу программы, однако вначале для построения таблицы символов требуется дополнительное время.

3. Выражения - переменные, структуры, списки и составные выражения.

Переменные бывают свободными и связанными. Структуры - предикаты разных арностей, факты и правила. Список - набор объектов одного доменного типа.

Составной объект или функтор - совокупность простых объектов. Составное выражение - функтор и совокупность альтернативных подобъектов.

Составная структура - объект или выражение (предикат в предикате) не имеет типа, но допускает списки составных структур.

4. Структура программы. Обычно программа на языке Турбопролог имеет в своем составе:

опции компилятора;

81

произвольное количество произвольно следующих друг за другом секций:

constants - объявление констант, domains - объявление типов данных, predicates - объявление предикатов, clauses - объявление фактов и правил;

программные секции:

goal - определение внутренней цели,

global domains ; global predicates - определение глобальных доменов и предикатов, что позволяет обеспечить межмодульный интерфейс.

Содержимое разделов constants и domains может отсутствовать, но для улучшения читаемости и ясности программы рекомендуется всегда описывать константы и домены в тексте.

Секция определения цели goal может быть только одна или может отсутствовать, если цель определяется в диалоге. Если секция goal присутствует, в ней определяется внутренняя цель, которую необходимо достичь для решения поставленной задачи. Цель может состоять из нескольких подцелей. Если разрабатываемая программа предназначена для работы в пакетном режиме, т.е. если необходимо создать exe-файл, секция goal не может быть опущена. Наконец, перед секцией predicates может быть дополнительный раздел

database - определение предикатов динамической базы данных. Таким образом, программа на языке Турбо-пролог может состоять из следующих секций: clauses, constants, database, domains, global domains, global predicates, goal, predicates.

Секцияdomains содержитвсеобъявления доменовчетырех форматов:

name = d

/* стандартный домен */

mylist = elementDom*

/* списочный домен */

myCompDom = f1(d11,d12,...,d1n); f2(d21,d22,...,d2n);

/* домен составного объекта */

 

file = name1; name2; ...; namen

/* файловый домен */

Секция predicates определяет предикаты (отношения). Каждый

предикат определяется со

своим именем и аргументами

(параметрами). Если типы данных некоторых аргументов предопределены, то они должны быть описаны заранее в разделе domains.

82

Раздел clauses определяет факты и правила.

Факт представляется именем предиката, за которым следуют объекты, заключенные в круглые скобки. Заканчивается запись факта точкой. Все имена предикатов должны начинаться со строчной буквы.

Правило состоит из заголовка и тела. Заголовок представляет собой предикат, тело состоит из термов, которые могут быть связаны между собой словами or или and (в транскрипции 'Turbo-Prolog' ";" и ","). Между заголовком и телом стоит знак ":-", означающий "если". Каждое правило должно заканчиваться точкой.

Имена переменных должны начинаться с прописной буквы и могут содержать буквы, цифры и знак подчеркивания "_". Максимальная длина имени - 250 знаков. Особую роль играют анонимные переменные, значения которых недоступны, они представляются знаком "_".

Комментарии могут располагаться в произвольных местах программы. Они начинаются с символов "/*" и заканчиваются символами"*/".

Пример правила для сложения двух десятичных чисел: sum(X,Y,Z) :– Z=X+Y.

5. Приемы повторения.

Предикат fail вызывает откат (бэктрекинг).

Предикат отсечения ! прерывает откат (бэктрекинг не распространяется на предшествующие предикаты).

Правила, выполняющие повторения, используют откат, а правила, выполняющие рекурсию, используют самовызов.

Вид правила, выполняющего повторение:

repetitive_rule :-

/* правило повторения */

< предикаты и правила >,

 

fail.

/* неудача */

Вид правила повторения, определяемого пользователем:

repeat.

 

/* повторить */

repeat :- repeat.

 

 

Вид правила, выполняющего рекурсию:

recursive_rule :-

 

/* правило рекурсии */

< предикаты и правила >,

 

 

recursive_rule.

 

 

Пример правила рекурсии

с

условием выхода - циклически

считывается введенный символ и,

если он не совпадает с некоторым

 

 

 

83

заданным символом, например, {, то выдается на экран, а при вводе

этого символа { рекурсия прерывается:

 

read_char :-

 

readchar(Char_data),

 

Char_data <> '{',

 

write(Char_data),

 

read_char.

 

Обобщенное правило рекурсии:

 

<имя правила рекурсии> :-

 

<список предикатов>,

(1)

<предикат условия выхода>,

(2)

<список предикатов>,

(3)

<имя правила рекурсии>,

(4)

<список предикатов>.

(5)

6. Встроенные предикаты обмена данными с экраном дисплея и клавиатурой (или файлом):

чтения строки символов целиком : readln(Line)

считывания целого числа с клавиатуры или из файла в переменную Num: readint(Num)

считывания десятичного числа с клавиатуры в переменную Val: readreal(Val)

считывания символа с клавиатуры в переменную Char: readchar(Char)

выдачи на экран (предикат с произвольным числом аргументов) строк и/или строковых переменных Name: write(" <строка1> ", Name1," <строка2> ", Name2,...," <строкаn> ", Namen)

перехода на новую строку экрана: nl

форматированного вывода: writef(FormatString, Arg1,Arg2, ...,

ArgN)

readdevice(myfile) и writedevice(yourfile) настраивают устройство ввода на файл myfile, а устройство вывода - на файл yourfile

по умолчанию устройство ввода - клавиатура, а устройство вывода - экран

переадресации вывода на принтер: writedev(printer)

7.Встроенные предикаты работы со строками для:

84

определения длины String_length некоторой строки String_value: str_len(String_value, String_length)

конкатенации (слияния) строк:

concat(Input_string1,Input_string2,Output_string)

создания из строки L подстроки L1 заданной длины N c

остатком в подстроке L2:

frontstr(N,L,L1,L2)

преобразования типов: upper_lower(S1, S2), str_char(S, C), str_int(S, I), str_real(S, R), char_int('S', N)

конкатенации префикса Char к строке Str: frontchar(Charstr, Char, Str)

проверки, является ли строка именем: isname(String)

формирования атома из строки: fronttoken(String, Token, Rest_of_string).

8.Примеры правил работы со строками:

соединения двух входных целых списков L1 и L2 с созданием выходного списка L3 с помощью некоторого списочного предиката soedin(integer*,integer*,integer*):

soedin([],L,L).

soedin([N|L1],L2,[N|L3]) :- soedin(L1,L2,L3)

преобразования строки в символ: conv(Str,Sym) :- Str=Sym

преобразования некоторой строки Str в список символов Sps:

cnv("", [])

cnv(Str, [Head|Tail] :- frontchar(Str, Head,Sps), cnv(Sps, Tail)

преобразования некоторой строки S в список атомов Tok: conv(S, [Head|Tail]) :- fronttoken(S, Head, Tok),!,conv(Tok,Tail). сonv(_, [])

9.Встроенные предикаты для работы с файлами:

уничтожение файла

deletefile(DOS_filename)

сохранение файла

save(DOS_filename)

переименование файла

renamefile(Old_DOS_filename, New_DOS_filename)

тест на наличие файла с данным именем

 

existfile(DOS_filename)

 

сброс данных из внутреннего буфера

flush(file_domain)

85

выбор пути доступа

disk(Path)

выдача каталога файлов с расширением File_spec с выбором

нужного в переменную File_name

 

dir(Path, File_spec, File_name)

 

закрытие файла встроенным предикатом

closefile(datafile)

обнаружение конца файла

eof(datafile)

выдача каталога файлов с расширением File_spec с выбором нужного в переменную File_name:

dir(Path, File_spec, File_name)

Пример описания файлового домена на три имени файлов DOS: file = datafile1; datafile2; datafile3

Пример открытия DOS-файла "FILE1.DAT" на чтение для файлового домена datafile1:

openread(datafile1, "FILE1.DAT").

Пример открытия DOS-файла "FILE1.DAT" на чтение и запись для файлового домена datafile1:

openmodify(datafile1, "FILE1.DAT").

Пример дозаписи в конец DOS-файла "FILE1.DAT" из файлового домена datafile1:

openappend(datafile1, "FILE1.DAT").

10.Встроенные предикаты динамической базы данных.

Раздел database предназначен для описания предикатов динамической базы данных, тогда как предикаты статической базы данных описываются в разделе predicates.

В динамической базе данных (ДБД) содержатся только факты, но не правила. ДБД состоит из резидентной части (находящейся в оперативной памяти) и долговременной части (находящейся в файле).

asserta(Clause) - занесение нового факта в резидентную часть ДБД перед всеми уже внесенными утверждениями данного предиката;

assertz (Clause) - занесение нового факта в резидентную часть ДБД после всех уже внесенных утверждений данного предиката;

retract(Clause) - удаление из резидентной части ДБД одного из ранее внесенных утверждений;

save(Dos_file_name) - перенос резидентной части ДБД в долговременную, т.е. из оперативной памяти в файл;

86

consult(Dos_file_name) - перенос долговременной части ДБД в резидентную, т.е. из файла в оперативную память;

readterm(dom, b(A1,A2,...,An)) - чтение из открытого файла значений аргументов A1,A2,...An данного домена dom, описанного в разделе domains как, например,

A1 = string

A2 = integer

. . .

An = real

dom = b(A1, A2. ..., An),

findall(Variable_name, Predicate_expression, List_name) - сбор

данных, относящихся к аргументу Variable_name,

входного

предиката

 

Predicate_expression, из ДБД в список List_name.

 

11. Примерыблоковэкспертнойсистемы, базирующейсянаправилах.

Интерфейсом реализуются следующие функции:

обработка данных, принимаемых с клавиатуры, и визуализация входных и выходных данных;

поддержка диалога между пользователем и системой;

распознавание ситуации непонимания между пользователем и системой;

обеспечение "дружественности" по отношению к пользователю.

Блоки строятся как наборы правил в разделе clauses. Трассы ответов клиента сохраняются в базе данных

database

qda(symbol,symbol)

qnet(symbol, symbol)

Целевое

правило do_usluga

создает дружественное меню,

облегчающее диалог, и исполняет экспертную функцию с помощью правила do_poisk, контролируя окончание диалога:

/*ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС*

do_usluga:- makewindow(1,7,6,"ЭКСПЕРТНАЯ СИСТЕМА",1,18,22,58), nl,write("**************************************************

******"),

nl,write("Нужна кошка"),

87

nl,write("Отвечайте только <да> или <нет>"), nl, do_poisk.

do_usluga:- nl, write("На выходENTER"),nl, readln(_),

removewindow, exit.

ask(X,Y):- write("Она ", X,Y), readln(Reply), remember (X,Y,Reply).

Продукционное правило исполнения экспертной функции do_poisk уточняет запрос клиента и запрашивает необходимую информацию в базе данных, сообщая результаты клиенту при успехе и извиняясь, если имеющихся данных недостаточно:

do_poisk:- variant(X),!,nl, write("Кошка для Вас - ",X," ."),nl, clear.

do_poisk:- nl,write("Жаль, не могу Вам помочь!"), clear.

Модуль вывода просматривает базу данных и оценивает ответы клиента:

da(X,Y):- qda(X,Y),!.

da(X,Y):- not(net(X,Y),!, ask(X,Y). net(X,Y):- qnet(X,Y),!.

запоминает их:

remember(X,Y, "да"):- asserta(qda(X,Y)). remember(X,Y,"нет"):- asserta(qnet(X,Y)),fail.

и очищает трассу ответов: clear:- retract(qda((_,_)), fail. clear:- retract(qnet(_,_)), fail.

Пользователь может пополнить набор правил этой экспертной системы, дописав нужные строки в раздел clauses, а затем повторить диалог:

/*ПРОДУКЦИОННЫЕ ПРАВИЛА */ variant("Мурка"):-

pasport("стоит","до 50$"), pasport("имеет возраст","4 года"),!.

variant("Кэтти"):-

88

pasport("стоит","от 50$"), pasport("имеет возраст","3 года"),!.

. . .

/*КОНЕЦ*/

89