- •Введение
- •1. Составление программ
- •1.1. Основные определения
- •1.2. Декларации в программах
- •1.3. Объявление предикатов и типов их аргументов
- •1.4. Другие разделы программы
- •Упражнения
- •2. Механизмы доказательства правил
- •2.1. Сопоставление с откатом
- •2.2. Рекурсия
- •Упражнения
- •3.Операции в Visual Prolog. Ввод-вывод
- •3.1. Операции
- •3.2. Предикаты ввода-вывода
- •4. Управление процессом доказательства правил
- •4.1. Искусственный откат
- •4.2. Отсечение
- •4.3. Повтор, определяемый пользователем
- •5. Списки
- •5.1. Процедуры обработки списков
- •5.2. Организация стеков и очередей
- •6. Внутренняя база фактов
- •7. Иерархическая организация данных
- •8. Работа с деревьями и графами
- •8.1. Двоичные деревья
- •8.2. Графы
- •9. Работа с именами и строками
- •Заключение
- •Библиографический список
- •Оглавление
1.2. Декларации в программах
Для того чтобы детально описать процесс работы Пролога, разберемся с терминологией.
В Прологе общим названием для объектов данных, участвующих в программе, является «терм» (term). Различают простые и составные термы.
К простым относятся константы и переменные. Среди констант различают числа, символические имена и строки. Символическое имя начинается со строчной буквы или знака подчеркивания и обозначает индивидуальный объект или понятие. Строка обрамляется двойными кавычками с обеих сторон и может начинаться с заглавной буквы. Так, имена «заяц», «капуста», ‘r’, ”Владимир” являются константами c различным представлением в памяти.
Переменная – имя, начинающееся с заглавной буквы: X, Человек, Владимир. Переменные могут быть свободными или связанными с какими-либо значениями. (Операции присваивания в Прологе нет, поэтому выражение «присваивание переменной значения» не употребляется).
Составной терм состоит из символического имени, которое называется функциональным символом, и упорядоченного множества простых и составных объектов, которые называются его аргументами. Функциональный символ не является именем функции в привычном смысле, а всего лишь описывает характер отношения объекта и аргументов, которые помещаются в круглые скобки и перечисляются через запятую. Например, терм «расстояние (точка (X,Y), точка (20, 45))» обозначает отношение между 2 объектами, каждый из которых задан отношением «точка» с двумя аргументами, причем в первом случае эти аргументы – переменные, а во втором – числовые константы.
Составной терм, у которого среди аргументов есть составные термы, называется структурой. Более подробно структуры рассмотрены в разд. 7.
Общее название для одноименных составных термов, имеющее одинаковое количество аргументов, – предикат(predicate). Например, предикат «животное (аргумент)» является названием для всех объектов c именем «животное» с любым аргументом из нашего примера: животное (волк), животное (заяц), животное (X). Предикатами являются отношение «ест (аргумент1, аргумент2)» и «хищник (аргумент). Предикат может быть истинен или ложен. Количество аргументов называется арностью предиката. Два предиката с одинаковым именем и различной арностью считаются различными. Когда рассуждают о предикатах, то называют их по имени с указанием арности: «животное/1» или «ест/2». В качестве имени предиката может быть использовано только символическое имя; строка не может быть именем предиката.
Аксиомы в Пролог-программах называются фактами. Согласно правилам языка, факт – это предикат, аргументами которого являются константы и который всегда является истиной. Последовательность перечисления аргументов в одноименных фактах с одинаковой арностью выбирается произвольно, но должна быть одинаковой во всей программе. Запись факта в программе заканчивается точкой.
Примеры утверждений на естественном языке и запись их в виде фактов:
яблоко, груша – фрукты → фрукты(яблоко, груша).
собака – друг человека → друг(человек, собака).
объект a зависит от n1 → a(n1).
Аня – сестра Маши → сестра(“Аня”, “Маша”).
Николай – мужчина лет сорока → мужчина(“Николай”, 40).
Количество фактов в программе формально неограниченно.
Формула вида (3), которая является формулировкой теоремы, в программе имеет такой же вид и называется правилом (rule). Левая часть правила – заголовок, правая – тело или хвост. Заголовок может состоять только из одного предиката, тело из нескольких, соединенных знаком коъюнкции «,» или дизъюнкции «;». Правило должно заканчиваться точкой. Область существования переменных, имеющихся в правиле, начинается от его заголовка и заканчивается точкой и не распространяется на другие правила.
Общее название для фактов и правил – предложения (clauses). Совокупность предложений программы называют базой знаний (БЗ). Пользователь, анализируя предметную область, описывает факты, формулирует правила и задает цель (goal) программы. После запуска программы автоматически включается механизм доказательства цели методом резолюций. Результат доказательства может быть успешен (цель достигается или создается в результате доказательства) или неуспешен (цель не может быть достигнута). Если в правилах есть переменные, то при достижении цели вычисляются их значения.
В общем случае целью может служить любое предложение программы с константами или переменными в качестве аргументов. Например, «животное (волк)» или «ест (Х, Y)». Такого рода цели называют простым запросом. Составной запрос составляется из нескольких предикатов, соединенных знаками конъюнкции или дизъюнкции, например, «животное(волк), ест(волк, Y)».
Однако обычно в качестве цели используется заголовок правила; в этом случае предикаты, входящие в тело правила, называются подцелями (subgoal). Так, если целью является предикат «хищник (Х)», то подцелями являются последовательно предикаты «животное (Х)», «животное (Y)» и «ест (X, Y)».
Предположим, что нам надо составить программу, которая отвечала бы на вопрос, с какой породой незнакомых собак надо быть осторожными. Интернет выдает список агрессивных собак, т.е. таких, которые могут напасть без всякого повода. Среди них есть таксы и чихахуа. Занесем их в базу данных программы как факты с аргументом «порода»:
агрессивная(такса).
агрессивная(чихуахуа).
Добавим спокойных собак – пуделя и немецкую овчарку.
спокойная(пудель).
спокойная(немецкая_овчарка).
Запишем следующее правило
осторожно(Х) :- агрессивная(Х),
которое читается так: если объект Х агрессивный, то с ним надо быть осторожным.
Добавим к фактам внешние признаки собаки: рост, окрас, длину шерсти. Эти сведения сформулируем как предикат «собака/4»:
собака( порода, рост, окрас, шерсть).
Для наших собак имеем:
собака(такса, маленький, мраморный, гладкая).
собака(чихуахуа, маленький, рыжий, гладкая).
собака(пудель, средний, черный, кудрявая).
собака(немецкая_овчарка, высокий, рыжечерная, жесткая).
Дополним правило для агрессивных собак
осторожно(Х) :- собака(X, Рост, Окрас, Шерсть), агрессивная(Х).
Если цель «осторожно» успешна, то значения переменных следующие:
X = такса Рост = маленький Окрас = мраморный
Шерсть = гладкая
X = чихуахуа Рост = маленький Окрас = рыжий
Шерсть = гладкая
Правило для спокойных собак:
не_опасайтесь(Y) :- собака(Y, Рост, Окрас, Шерсть), спокойная(Y ).
Y= пудель Рост=средний Окрас=черный Шерсть=кудрявый
Y=немецкая_овчарка Рост= высокий Окрас=рыжечерная Шерсть=жесткошерстная.
До сих пор правила были сформулированы так, что правило было истинным только в том случае, когда все предикаты, входящие в тело, были истинными. Предположим теперь, что цель может быть достигнута, если хотя бы один из нескольких предикатов является истиной. Такие предикаты соединяются знаком дизъюнкции «;». Например, из базы знаний для собак следует, что с конкретной собакой нужно вести себя или осторожно или не опасаться ее. Это заключение можно выразить с помощью следующего правила
xарактер_собаки(X):-осторожно(X); не_опасайтесь(X).
Теперь мы можем задавать в программе одну цель – «xарактер_собаки». При этом для каждой породы истинным будет только одно правило из двух. Например, по запросу «xарактер_собаки(такса)» таковым является «осторожно». Для цели «xарактер_собаки(пудель)» - «не_опасайтесь».
Обычно, в программах правило с дизъюнкцией разделяют на несколько одноименных правил, записываемых последовательно:
xарактер_собаки(X):- осторожно(X).
характер_собаки(X):-не_опасайтесь(X).
и называют процедурой.
(Так как цель «характер_собаки» всегда доказывается, то практического значения это правило не имеет. Его целесообразно дополнить соответствующими сообщениями, выводимыми на консоль. Например, так
xарактер_собаки(X):-осторожно(X), write(“Осторожно”);
не_опасайтесь(X),write(“Не опасайтесь”).
Подробнее о предикатах ввода-вывода см. подразд. 3.2 )
В правилах вместо имени переменной можно записывать символ подчеркивания. В этом случае переменная называется анонимной. Анонимная переменная может быть использована на месте любой переменной; она не связывается с каким-либо значением. Например, если из всех признаков агрессивных собак нас интересует только рост, то соответствующее правило можно записать так
осторожно(Х) :- собака(X, Рост, _, _), агрессивная(Х).
