4.1. Ввод/вывод
4.2. Управление экраном и оконная система
4.3. Обработка строк
4.4. Преобразование типов
4.5. Работа с базой данных
4.6. Управляющие предикаты
4.7. Прочие стандартные предикаты
4.8. Арифметические и логические предикаты..
Приложение
Одной из
основных
причин,
которые
помогли Прологу
стать
"реальным"
языком
программирования,
было
введение в
язык
элементов, лежащих
за пределами
чистой
логики. В
Турбо-Прологе
такие
элементы
реализованы
как стандартные
(встроенные)
предикаты.
Большинство
стандартных
предикатов
выполняет
несколько
функций в
зависимости
от состояния
параметров,
входящих в
предикат. В
одном случае
заранее
определен
какой-либо
один
параметр, в
другом
случае
известны
другие
параметры,
иногда к
моменту обращения
могут быть
известны все
параметры.
Известные
параметры
предиката
называются
входными,
неизвестные
– выходными.
Совокупность
входных и
выходных
параметров
определяет
работу
предиката.
Эта совокупность
называется
поточным
шаблоном. Если
предикат будет
вызываться с
двумя
аргументами,
имеется
четыре
варианта
поточного
шаблона:
(i,i)
(i,o)
(o,i)
(o,o),
где i –
входной
параметр, о
– выходной
параметр.
Однако не для
каждого
предиката
все
возможные
варианты поточного
шаблона
имеют смысл.
Hиже
приводятся
некоторые
наиболее
часто употребляемые
стандартные
предикаты,
сгруппированные
в отдельные
классы по их
функциональному
назначению.
Более полный
список
стандартных
предикатов
можно найти в
[3].
readln(StringVariable)
(string) – (o)
Считывает
строку с
текущего
устройства ввода
и связывает
ее с заданной
переменной StringVariable.
Обычно
чтение
производится
с клавиатуры.
В качестве
конца строки
используется
символ
возврата
каретки. Readln
считывает до 150
символов в
строке при
вводе с
клавиатуры и
до 64К при
вводе с
других
устройств.
readint(IntgVariable)
(integer) – (o)
Читает целое
число с
текущего
устройства ввода
и связывает
его с
заданной
переменной.
readreal(RealVariable)
(real) – (o)
Читает действительное
число с
текущего
устройства
чтения и
связывает
его с
заданной
переменной RealVariable. Обычно
чтение
производится
с клавиатуры.
readchar(CharVariable)
(char) – (o)
Читает
символ с
текущего
устройства
ввода и
связывает
его с
заданной
переменной CharVariable. В
отличие от inkey
устанавливает
режим
ожидания
ввода.
inkey(CharVariable)
(char) – (o)
Читает
символ со
стандартного
устройства
ввода. В
отличие от
предиката readchar
выполнение
программы не
прерывается.
Поэтому inkey
применяют
главным
образом для
организации
циклов
ожидания.
keypressed
Выполняется
успешно, если
нажата
некоторая
клавиша. В
отличие от
предиката inkey с
помощью keypressed
можно
установить,
нажата ли
клавиша, не
читая при
этом
введенный с
клавиатуры
символ.
write( Variable|Constant * )
Запись
заданных
значений
переменных и
констант в
заданное
активное
окно на
текущем
устройстве
вывода.
nl
Вызывает
возврат
каретки и
перевод
строки.
Пролог
позволяет
управлять
следующими характеристиками
экрана:
инверсным
изображением,
подчеркиванием
и цветом. Эта
информация
задается в
стандартных
предикатах
посредством
значений
атрибутов.
Можно
задавать
цвет
переднего
плана и фона,
а также
отдельных
символов и
всего экрана.
В таблице,
приведенной
ниже, даны значения
атрибутов
для цветного
графического
дисплея.
Фон |
Передний план |
Черный 0 |
Черный 0 |
Голубой 16 |
Голубой 1 |
Зеленый 32 |
Зеленый 2 |
Бирюзовый 48 |
Бирюзовый 3 |
Красный 64 |
Красный 4 |
Алый 80 |
Алый 5 |
Коричневый 96 |
Коричневый 6 |
Белый 112 |
Белый 7 |
Кроме того,
при сложении
значения
атрибута с 1
символы
подчеркиваются.
Сложение
значения
атрибута с 8
усиливает
интенсивность
цвета. При
сложении
значения
атрибута со 128 происходит
мерцание символов.
Пролог
поддерживает
развитую
оконную систему.
Для ее
организации
используются
следующие
стандартные
предикаты:
makewindow(WindowNo, ScrAtt, FrameAtt, Framestr, Row, Column, Height, Width)
(integer,integer,integer,string,integer,integer,integer,integer)
- (i,i,i,i,i,i,i,i) (o,o,o,o,o,o,o,o)
Определяет
для (i,i,i,i,i,i,i,i)
область
экрана в
качестве
окна. Каждое
окно
задается
номером WindowNo.
ScrAtt задает
значение
атрибута для
всех позиций
описываемого
окна. Если FrameAtt
не равно 0,
окно берется в
рамку и
верхняя
граница
включает
текст Framestr.
Позиция
левого
верхнего
угла окна
задается
параметрами Row и Col.
Параметры Height и Width
определяют
соответственно
высоту и ширину
окна, которые
должны быть
совместимыми
с размерами
экрана. В
случае (о,о,о,о,о,о,о,о)
связывает
характеристики
текущего
окна с
выходными
параметрами.
shiftwindow(WindowNo)
(integer) – (i) (o)
Активизирует (i) окно с номером WindowNo.
Окно должно
быть создано
заранее.
Связывает (o) c
параметром
"номер
текущего
окна".
removewindow
Удаляет
текущее
активное
окно.
clearwindow
Очищает
текущее
активное
окно.
cursor(Row,Column)
(integer,integer) – (i,i)
(o,o)
Для (i,i)
помещает
курсор в
позицию с
координатами
(Row,Column) или
присваивает
переменным Row и Column
значения
текущих
координат
курсора при (o,o).
Предикаты обработки строк используются для разделения строк либо на список отдельных символов, либо на список заданных групп символов.
frontchar(String,FrontChar,RestString)
(string,char,string) – (i,o,o)
(i,i,o) (i,o,i) (i,i,i) (o,i,i)
Разделяет
заданную
строку String
согласно
поточному
шаблону на
две части: первый
символ FrontChar
и оставшаяся
часть строки RestString.
fronttoken(String,Token,RestString)
(string,string,string) – (i,o,o)
(i,i,o)(i,o,i) (i,i,i) (o,i,i)
Разделяет строку, заданную параметром String, на
лексему Token и остаток RestString согласно поточному шаблону. (Лексема
– это
последовательность
символов,
имеющих
смысл. Она
определяется
либо как имя
в соответствии
с синтаксисом
Турбо-Пролога,
либо как
строчное
представление
числа, при
этом знак
возвращается
отдельно,
либо как
отдельный
символ.)
frontstr(Lenght,Inpstring,StartString,RestString)
(integer,string,string,string) – (i,i,o,o)
Разделяет строку Inpstring
на две части. StartString
будет иметь
длину Lenght
первых
символов
исходной
строки, RestString
представляет
собой
остаток
строки InpString.
concat(String1,String2,String3)
(string,string,string) – (i,i,o)
(i,o,i) (o,i,i) (i,i,i)
Слияние строк, согласно поточному шаблону, по формуле: String3 = String1 + String2.
str_len(String,Length)
(string,integer) – (i,i)
(i,o) (o,i)
Определяет длину Length строки String.
isname(StringParam)
(string) – (i)
Завершается успешно, если StringParam
есть имя, удовлетворяющее синтаксису Пролога.
Стандартные предикаты данной группы служат для преобразования символов с десятичным кодом ASCII, строк с отдельным символом, строк с целыми и действительными числами, а также строчных букв латинского алфавита с соответствующими прописными буквами.
char_int(CharParam,IntgParam)
(char,integer) – (i,o)
(o,i) (i,i)
Преобразует символ в код ASCII, согласно поточному шаблону.
str_int(StringParam,IntgParam)
(string,integer) – (i,o) (o,i) (i,i)
Строка, представляющая целое десятичное число, преобразуется в это число.
str_char(StringParam,CharParam)
(string,char) – (i,o)
(o,i) (i,i)
Один знак как строка преобразуетс в символ.
str_real(StringParam,RealParam)
(string,real) – (i,o)
(o,i) (i,i)
Строка, представляющая десятичное число, преобразуется в это число.
consult(DosFileName)
(string) – (i)
Добавляет
текстовый
файл с именем
DosFileName к
текущей базе
данных.
Текстовый
файл может
быть,
например,
создан в
результате
выполнения
предиката save. Этот файл
содержит
факты,
которые
должны быть
описаны в
разделе DbaseDom.
Выполнение
предиката не
будет
успешным, если
в файле
имеются
синтаксические
ошибки.
save(DosFileName)
(string) – (i)
Записывает
динамическую
базу данных
на диск в
текстовый
файл с именем
DosFileName.
После этого
файл можно
снова
загрузить в оперативную
память,
используя
предикат consult.
Для хранения
каждого
факта
используется
отдельная
строка.
Текстовый
файл, представляющий
собой всю
базу данных,
можно просмотреть
и изменить,
используя
редактор
Пролога.
asserta( Term )
(DbaseDom) – (i)
Заносит факт Term в базу
данных перед
другими
фактами. Факт
должен быть
термом,
принадлежащим
области определения
DbaseDom.
assertz( Term )
(DbaseDom) – (i)
Заносит факт Term в
конец базы
данных. Факт
должен быть
термом,
принадлежащим
области
определения DbaseDom.
retract( Term )
(DbaseDom) – (_)
Удаляет
первый факт
из базы
данных,
который
соответствует
заданному
факту Term.
retractall(Term)
(InternalDatabaseDomain) – (_)
Очищает всю базу данных.
exit
Выполняет
немедленный
выход из
программы.
fail
Вынуждает
завершиться
предикат
ложно и, следовательно,
возвратиться
к предыдущей
точке
разветвления
(backtracking).
true
Значение
предиката
всегда
истинно.
!
Отсечение
(прекращение
перебора между
головой
дизъюнкта и
данным
знаком).
random(RealVariable)
(real) – (o)
Равномерное
псевдослучайное
число в диапазоне
от 0 до 1.
random(MaxValue,RandomInt)
(integer,integer) – (i,o)
Равномерное
псевдослучайное
целое число RandomInt в
диапазоне от
0 до MaxValue.
findall( Variable, Atom, ListVariable )
В списке ListVariable
возвращаются
все решения
для
переменной Variable
предиката Atom.
not( Atom
)
Выполняется
успешно, если
заданный Atom
представляет
собой цель,
которая не
достигается.
free( Variable
)
Выполняется
успешно, если
Variable не
является
конкретизированной
переменной.
bound( Variable )
Выполняется
успешно, если
Variable
является
конкретизированной
переменной.
В арифметических
операциях
могут
участвовать
операнды
(числа и
переменные),
арифметические
операции +
(сложение), –
(вычитание), *
(умножение), /
(деление), mod
(деление по
модулю), div
(целочисленное
деление),
скобки.
Приоритет
выполнения
операций
представлен
числами:
|
1 |
* , / |
2 |
div ,mod |
3 |
– ,+ (унарные) |
4 |
Логические операторы:
|
Больше |
< |
Меньше |
= |
Равно |
>= |
Больше или равно |
<= |
Меньше или равно |
< > |
Не равно |
Арифметические функции:
|
Синус, угол в радианах |
cos(Х) |
Косинус, угол в радианах |
tan(Х) |
Тангенс, угол в радианах |
arctan(Х) |
Арктангенс |
ln(Х) |
Логарифм натуральный |
log(Х) |
Логарифм десятичный |
abs(X) |
Модуль аргумента |
exp(Х) |
Экспонента |
sqrt(Х) |
Корень квадратный |
Кроме этих
предикатов, в
Прологе
имеется большой
набор стандартных
предикатов
для
построения
графических
объектов.
Просмотреть
названия и
поточный
шаблон
стандартных
предикатов
графики
можно в
разделе HELP
меню
интегрированной
среды
Пролога.
1. Родословное
дерево
1. Составить
родословную
своей семьи, использовав
10-12 отношений родитель.
Определить
предикат пол
для каждого
члена семьи.
2. Определить
предикаты мать,
отец, дядя,
тетя, кузен,
дед, внук.
3. Определить
рекурсивный
предикат предок.
5. Определить
предикат найти_тетю(Х)
, выдающий
информацию о
наличии
(отсутствии)
тети у
личности Х.
Определить
предикаты о
наличии
прочих родственников
у личности Х.
6. Определить
предикат,
дающий
список всех родственников
личности Х.
Переменную Х
ввести.
2.
Вопросно-ответная
система
Вариант 1. Что
делать, если
Вы заболели?
Если у Вас грипп
и Вы
находитесь в
уязвимом
возрасте, то
вызовите
врача.
Если у Вас
острый
фарингит, то
вызовите врача.
Если у Вас
простуда, то
примите
аспирин и ложитесь
в постель.
Если у Вас грипп
и вы не
находитесь в
уязвимом
возрасте, то
примите
анальгин и
ложитесь в
постель.
Если у Вас
лихорадка и
болят мышцы,
то это грипп.
Если у Вас
насморк,
мышечные
боли и нет
лихорадки, то
это
простуда.
Если у Вас в
горле нарывы
и есть лихорадка,
то это острый
фарингит.
Если Вам
меньше 8 или
больше 60 лет,
то Вы находитесь
в
уязвимом
возрасте.
Вариант 2.
Продажа
бухгалтерских
программ.
1. Если класс
бухгалтерские
программы и
форма
конфигурации
системы
должна быть
жесткой, то
лучше всего
для вас
подходит
бухгалтерская
программа "1С
версия 6.0".
2. Если класс
бухгалтерские
программы и
форма
конфигурирования
системы
должна быть лояльной
и программа
разработана
под оболочку
DOS, то лучше
всего
подходит
система бухгалтерских
программ
"Бест".
3. Если класс
бухгалтерские
программы и
форма
конфигурирования
системы
должна быть лояльной
и программа
разработана
по оболочку Windows и
программа
одноуровневая,
то лучше
всего вам
подходит
бухгалтерская
программа "Инфо
бухгалтер".
4. Если класс
бухгалтерские
программы и
форма
конфигурирования
системы
должна быть
лояльной и
программа
разработана
по оболочку Windows и
программа не
одноуровневая,
то лучше всего
вам подходит
бухгалтерская
программа "Турбо
бухгалтер".
5. Если тип
"складские
программы" и
форма конфигурации
системы
должна быть
жесткой, то
лучше всего
для вас
подходит
складская программа
"Фолио".
6. Если тип
"складские
программы" и
форма конфигурации
системы
должна быть
лояльной, то
лучше всего
для вас
подходит
программа "1С
склад версия
7.5".
3. Работа со
списками
Вариант 1.
В спортивных
соревнованиях
результат спортсмена
оценивается
информационной
единицей
вида:
оценка(<фамилия>,
<спортивный
разряд>,
<список оценок>)
Чтобы
выставить
оценку
спортсмену,
надо из
списка
оценок
удалить
одну
минимальную,
одну
максимальную,
а для
оставшихся
оценок найти
среднюю
арифметическую.
1. Записать
правило
"оценка
_спортсмена".
2. Определить
предикат
"мастер",
если средняя
оценка
спортсмена
больше 5.5 и
спортсмен имеет
первый
разряд.
3. Определить
предикат
"аутсайдер",
если среди
оценок есть
минимальная. Минимальную
оценку
ввести.
Вариант 2.
Продуктовая
фирма
производит
готовые салаты.
Имеется
информация
вида
салат(
<название
салата>,
<список
ингредиентов>
).
продукты_экзотические(
<список
экзотических
продуктов> ).
морепродукты(
<список
морепродуктов>
).
1. Определить
предикат "сложный_салат",
если число
ингредиентов
больше 5.
2. Определить
предикат "витаминный_салат",
если в состав
салата
входит сырая
морковь или
овсяные
хлопья.
3. Определить
предикат "морской_салат",
если в состав
входят
морепродукты.
4. Определить
предикат "экзотический_салат",
если в состав
входят, по
крайней мере,
два экзотических
продукта.
4. Поиск пути
на графе.
Вариант 1.
Задана
система
двусторонних
дорог, причем
для любой
пары можно указать
соединяющий
их путь.
Найти такой город,
для которого
сумма
расстояний
до остальных
городов
минимальна.
Вариант 2.
Задана
система
двусторонних
дорог. N-периферией
называется
множество
городов, расстояние
от которых до
выделенного
города (столицы)
больше N.
Определить
N-периферию
для
заданного
города G
(среди всех
возможных
расстояний от
столицы до
заданного
города
следует выбирать
минимальное).
5.
Разработайте
прототип
классификационной
экспертной
системы
За основу
взять одну из
программ
классификации.
Дополните
программу
механизмом
объяснений,
возможно,
обработки
негативных
признаков,
загрузки
базы данных,
множественных
значений
лингвистических
переменных, просмотра
правил. Выберите
в качестве
предметной
области одну
из
предложенных
тем:
а) приобретение
автомобиля (в
зависимости
от марки машины,
стоимости,
места сборки
и т.д.);
б) выбор
подарка в
магазине
(мужчине,
женщине,
возраст,
стоимость и
т.д.);
в) выбор
книги для
чтения в
библиотеке;
г) где
провести
каникулы
(зимой, летом,
дом отдыха,
турбаза, развлечения);
д)
определитель
растений,
птиц, грибов
и т.д.;
е) куда пойти
учиться?
6.
Построение
синтаксического
анализатора
Напишите
систему
грамматического
разбора
предложения
по группам
подлежащего,
сказуемого,
предлога и
т.д., для
одного из
следующих
примеров:
John
makes good coffee for his friends.
Starkid paints his spaceship
every year.
I usually get up at
First I bought new space shoes.
The sport shop is opposite the hotel.
Пример №1:
/*
Copyright (c) 1986, '92 by Prolog Development Center */
domains
my_dom = f(string)
db_selector = my_dba
predicates
write_dba(integer)
read_dba
rd(Ref)
count_dba(integer)
count(Ref, integer, integer)
replace_dba
replace(Ref)
double_dba
double(Ref)
half_dba
half(Ref)
mixture
clauses
write_dba(0) :- !.
write_dba(N) :-
chain_inserta(my_dba, my_chain, my_dom, f("Prolog system"), _),
chain_insertz(my_dba, my_chain, my_dom, f("Prolog Compiler"), _),
N1=N-1,
write_dba(N1).
read_dba :-
db_chains(my_dba, Chain),
chain_terms(my_dba, Chain, my_dom, Term,
Ref),
write("\nRef=",
Ref, ", Term=", Term),
fail.
read_dba :-
db_chains(my_dba, Chain),
chain_first(my_dba, Chain, Ref),
rd(Ref),
fail.
read_dba.
rd(Ref) :-
ref_term(my_dba, my_dom, Ref, Term), nl,
write(Term), fail.
rd(Ref) :-
chain_next(my_dba, Ref, Next), !, rd(Next).
rd(_).
replace_dba :-
chain_first(my_dba, my_chain, Ref),
replace(Ref).
replace(Ref) :-
term_replace(my_dba, my_dom, Ref,
f("Prolog Toolbox")),
chain_next(my_dba, Ref, NN),
chain_next(my_dba, NN, Next), !,
replace(Next).
replace(_).
half_dba :-
chain_last(my_dba, my_chain, Ref),
half(Ref).
half(Ref) :-
chain_prev(my_dba, Ref, PP),
chain_prev(my_dba, PP, Prev), !,
term_delete(my_dba, my_chain, Ref),
half(Prev).
half(_).
double_dba :-
chain_first(my_dba, my_chain, Ref),
double(Ref).
double(Ref) :-
chain_next(my_dba, Ref, Next), !,
chain_insertafter(my_dba, my_chain, my_dom, Ref,f("Programmers
Guide"), _),
double(Next).
double(_).
count_dba(N) :-
chain_first(my_dba, my_chain, Ref),
count(Ref, 1, N).
count(Ref, N, N2) :-
chain_next(my_dba, Ref, Next), !,
N1=N+1,
count(Next, N1, N2).
count(_, N, N).
mixture :-
write("\nReplace
every second term:"),
replace_dba,
write("\nDouble
the number of terms:"),
double_dba,
write("\nErase
every second term:"),
half_dba,
write("\nUse
ref_term for all terms:"),
read_dba,
count_dba(N),
write("\nThere
are now ", N, " terms in the database"),
db_statistics(my_dba, NoOfTerms, MemSize, DbaSize, FreSize),
writef("\nNoOfTerms=%, MemSize=%, DbaSize=%, FreeSize=%", NoOfTerms, MemSize,DbaSize,FreSize).
goal
write("\n\n\n\tTEST
OF DATABASE SYSTEM\n\t***********************\n\n"),
time(H1, M1, S1, D1),
db_create(my_dba, "dd.dat", in_memory),
write("\n\nWrite
some terms in the database:"),
write_dba(50),
read_dba,
mixture,
write("\n\n\nCopy
to file"),
db_copy(my_dba, "dd.dat", in_file),
db_close(my_dba), db_delete("dd.dat", in_memory),
db_open(my_dba, "dd.dat", in_file),
mixture,
db_close(my_dba),
write("\n\n\nOpen
the database on file"),
db_open(my_dba, "dd.dat", in_file),
mixture,
db_close(my_dba),
time(H2, M2, S2, D2),
Time = (D2-D1)+100.0*((S2-S1)+60.0*((M2-M1)+
60.0*(H2-H1))),
write("\n\nTime
= ", Time, "/100 Sec" ), nl.