
3к6с Интеллектуальные системы и технологии / С ИОС / МУ ПР4
.pdfПРАКТИЧЕСКАЯ РАБОТА №4
Цель работы: изучить основные языковые конструкции языка Пролог.
ОБЩИЕ СВЕДЕНИЯ
Название Пролог (Prolog) произошло от словосочетания «программирование при помощи логики» (PROgramming in LOGic). Теоретической основой языка Пролога является раздел символьной логики, называемый исчислением предикатов.
Создание логического программирования можно приписать Роберту Ковальскому и Алэну Колмероэ. Р. Ковальский разработал процедурную интерпретацию хорновских дизъюнктов. В начале 70-х годов А. Колмероэ и его группа создали в Марсельском университете (Франция) специальную, написанную на Фортране программу, предназначенную для доказательства теорем. Программа доказательства теорем, названная Прологом, включала в себя интерпретатор Р. Ковальского. С тех пор было сделано несколько расширений и усовершенствований языка. Здесь можно отметить работу группы из Эдинбургского университета (Шотландия). Шотландский вариант получил название C&M Prolog в честь авторов классической работы «Программирование на языке Пролог» Уильяма Клоксина и Кристоффера Меллиша. Сегодняшней своей популярности Пролог во многом обязан эффективной реализации этого языка, полученной в Эдинбурге Дэвидом Уорреном и его коллегами в конце 70-х годов. Написанный ими компилятор (компилятор был почти полностью написан на Прологе) остается и поныне одной из лучших реализаций Пролога.
В то время, как традиционные языки программирования являются процедурноориентированными, Пролог основан на описательной или декларативной точке зрения на программирование. Это означает, что машине в качестве программы можно предоставить не алгоритм, а формальное описание предметной области и задачи в виде аксиоматической системы, и тогда построение решения задачи в виде вывода в этой системе можно поручить самой машине. Таким образом, от программиста не требуется построение алгоритма, решающего задачу, поскольку нужный алгоритм порождается интерпретатором, строящим вывод по определенной стратегии. Теперь основная задача программиста – удачно аксиоматизировать, т.е. описать в виде системы логических формул предметную область и такое множество отношений на ней, которые с достаточной степенью полноты описывают задачу.
Язык программирования Пролог базируется на ограниченном наборе механизмов, включающих в себя сопоставление образцов, древовидное представление структур данных и автоматический возврат. Пролог очень полезен в некоторых проблемных областях, подобных искусственному интеллекту, разработке экспертных систем, обработке естественного языка, и т.д., но совершенно бесполезен в других, таких как графика или числовые алгоритмы.
ЭТАПЫ ПРОГРАММИРОВАНИЯ НА ПРОЛОГ
Программирование на языке Пролог состоит их 3-х этапов:
1. Определение фактов предметной области.
Факты могут описывать свойства объектов и отношения между объектами. Например, факт «нравится ellen tennis» можно записать так:
likes(ellen, tennis).
Этот факт включает в себя два объекта, обозначенных словами ellen и tennis, и отношение, обозначенное словом likes (нравится). Обратите внимание, что каждый факт и каждое правило предметной области должны заканчиваться точкой. Имена объектов, список которых в каждом факте заключен в круглые скобки, называются аргументами. Имя отношения – называется предикатом. Таким образом, likes – предикат с двумя аргументами.
1
2. Определение правил.
Правило – это факт, истинность значения которого зависит от истинности других фактов. Правила позволяют получать новые факты исходя из уже имеющихся.
Общий вид правила:
A :- B1, ..., Bn. (n>0)
Здесь A – заголовок правила, Bi – тело правила. Символ «:-» читается «если». Возможны два варианта прочтения данного правила:
декларативное прочтение – «A истинно, если истинны Bi»;
процедурное прочтение – «чтобы решить задачу A, сначала надо решить подзадачу B1, затем подзадачу B2, ..., затем подзадачу Bn»
Таким образом, для выполнения цели в заголовке правила, необходимо вначале
выполнить (согласовать) все подцели из тела правила.
Например, правило «тому нравится футбол, если футбол является видом спорта» на Прологе можно записать следующим образом:
likes(tom, football) :- sport(football).
Цель likes(tom, football) будет истинной в том случае, если выполняются все подцели из тела правила. В данном случае подцель sport(football).
3. Формулировка вопросов об объектах предметной области и отношениях между ними.
Имея некоторую совокупность фактов, мы можем обращаться к Прологу с вопросами о них.
Например, пусть имеется следующая совокупность фактов: likes(ellen, tennis).
likes(tom, football). likes(tom, swimming).
Теперь мы можем задать системе вопрос «нравится ли тому футбол»:
?- likes(tom, football) yes
Поскольку нужный факт имеется в базе фактов и правил, получен положительный
ответ.
ОСНОВНЫЕ ПОНЯТИЯ ПРОЛОГА
Рассмотрим основные понятия Пролога.
В качестве простых объектов данных в Прологе используются константы и переменные.
Константы представляются как числа, символы и атомы. Числа и символы понимаются в традиционном смысле.
Примеры констант: -67, 5, „s‟, „/‟, 3.14
Для констант могут быть введены символические имена, которые будут использоваться в тексте программы вместо самой константы. Например, pi = 3.14 или zero=0. Для этого служит специальная секция CONSTANTS.
Атом - это строка символов, которая начинается со строчной буквы и обозначает некоторый неделимый абстрактный объект.
Если строка атома начинается с прописной буквы или содержит специальные символы типа дефис, знак доллара и т.п., то она заключается в двойные кавычки.
Примеры атомов: машина, иван, “ кто-то ”, “Иван”, “иван”.
2
Здесь иван и “иван” – это один и тот же атом, но “Иван” и “иван” - разные
Переменная - это строка символов, которая начинается с прописной буквы или ее первый символ подчеркнут.
Примеры переменных: Иван, Студент, Z34, xyz, _test.
Переменная может находиться в свободном(free) или связанном (bound) состоянии. Причем переменные не предназначены для хранения значений, т.е. им нельзя явно присвоить какое-либо значение. А связанными они становятся в процессе проверки утверждений Пролога.
Ксложным (составным) объектам данных в Прологе относятся структуры и списки.
Структура - это объект, который имеет имя (функтор), начинающееся с буквы, и список аргументов, заключенных в круглые скобки и разделенных запятыми.
Регистр символов в имени структуры не имеет значения, но рекомендуется не использовать прописные символы. Спецсимволы '$‟, „-„, „?‟ и другие, за исключением символа подчеркивания нельзя использовать в именах структур.
Аргументами могут быть числа, атомы, переменные, структуры и другие сложные объекты. Однако, количество компонент структуры фиксировано и не может меняться в процессе выполнения программы. Вообще говоря, могут использоваться и структуры без аргументов.
Примеры структур:
граф (a,b,c,d,u,v,x)
студент( иванов, иван, возраст)
имеет("Иван", Машина)
зеленый(дерево)
наша_семья (дедка, бабка, внучка, собака(жучка), кошка (мурка), Мышка)
Если внимательно посмотреть на приведенные примеры, то видно, что синтаксически они записаны одинаково, но имеют несколько разный характер.
Граф состоит из вершин a,b,c,d,u,v,x .
Каждый «студент» описывается такими свойствами как фамилия, имя, возраст. Наша семья состоит из … и перечисляется состав.
Иван имеет машину.
Дерево описывается свойством "цвет" и значение у этого свойства - зеленый.
Таким образом, примеры 1 и 5 определяют новые объекты через другие объекты, пример 2 – как комбинацию свойств. Пример 3 определяет отношение между Иваном и машиной. А пример 4 выделяет одно из свойств объекта. Эти примеры подчеркивают, что синтаксически одинаковая запись в Прологе может быть использована как для представления сложного объекта - структуры, так и для представления отношения между объектами или описания свойств объектов (т.е. унарных отношений).
Отношения в Visual Prolog называются предикатами и записываются они так же как структуры. Для того, чтобы Пролог мог отличить где объект данных, а где – отношение, необходимо их явно описать.
Соответственно, все структуры должны быть описаны в секции DOMAINS вместе с пользовательскими типами данных. А все используемые в программе предикаты (кроме встроенных) - в секции PREDICATES.
Кроме того при описании предикатов могут быть заданы такие их свойства как
неоднозначность результата – nondeterm, determ;
схема использования аргументов – вход(i), выход(o).
Примеры предикатов:
3
получил_оценку("Петров",5) отличная(Оценка)
обучает(профессор, студент, дисциплина) Примеры описания предикатов:
DOMAINS
студент = symbol профессор=symbol дисциплина=symbol
оценка=integer
PREDICATES
nondeterm получил(студент, оценка)
determ получил_оценку_по_дисциплине(студент, оценка, дисциплина) обучает(профессор, студент, дисциплина)
Здесь студент может иметь несколько оценок по разным предметам, поэтому предикат неоднозначен. Но оценка по каждой дисциплине может быть только одна.
ВПрологе существует множество встроенных специальных предикатов. Например,
предикат без аргументов «nl» определяет печать с новой строки;
предикаты free(Var) и bound(Var) проверяют является ли переменная Var, соответственно, свободной или связанной;
предикат findall формирует список из всех возможных решений, обеспечивающих истинность некоторого неоднозначного предиката (См. пример «Сколько свободных столиков»).
Другим сложным объектом данных Пролога является список.
Cписок - это объединение произвольного количества объектов, разделенных запятыми и заключенных в квадратные скобки.
Список не имеет имени, а количество его элементов может меняться. Примеры списков:
[3,5,4]
[собака, кошка, хомяк, крокодил]
[петров, [ иванов, сидорова], сидоров, козлова]
[[4,5,3],[4,4,5],[2,2],[ ],[5,5,5]]
[ ] – пустой список
Следует подчеркнуть, что атом “иван” и список [“иван”], состоящий из единственного элемента “иван” – это разные объекты данных.
Чтобы использовать список, надо сначала описать его домен. Например,
DOMAINS
персонал = сотрудник* сотрудник = преподаватель; инженер преподаватель, инженер = symbol
Здесь именно символ «*» определяет персонал как список сотрудников.
Символ запятая (,) определяет логическое «и», а символ двоеточие (;) – логическое
«или».
4
Подчеркнем, что можно создавать список из любых элементов, включая другие списки. Но все элементы одного списка должны принадлежать одному и тому же домену.
Список представляет собой рекурсивный объект. Поэтому любой список (кроме пустого) можно разбить на «голову», совпадающую с первым элементов этого списка, и «хвост», который включает все его остальные элементы кроме первого.
Голова списка – элемент, а хвост – всегда список. Например, голова списка [s] – это “s”, а хвост равен [ ]. Если достаточное число раз отделить первый элемент списка, то получим в конце концов пустой список.
Для отделения головы от хвоста Пролог использует специальный выделенный символ
“|”. Например, [a,b,c] эквивалентно [a | [b,c] ] и далее [a | [ b | [c ] ] ] и [a | [ b | [ c | [ ] ] ] ].
Основная операция над объектами в Прологе - это унификация (иногда называют сопоставление, согласование, конкретизация). По своей сути унификация - это сравнение объектов или их совокупностей.
Правила унификации:
число сопоставляется только с равным ему числом,
атом сопоставляется только с равным ему атомом,
переменная сопоставляется с любым объектом и получает значение того, с чем сопоставляется,
структура сопоставляется с другой структурой, если число их компонент и функторы (имена) совпадают, а компоненты попарно сопоставимы.
Очевидно, что операция сопоставления может кончиться неудачно. Примеры унификации:
9 сопоставляется с 9
"иван" сопоставляется с иван
"иван" не сопоставляется с "петр"
имеет (иван, машина) не сопоставляется с имеет (иван, канарейка)
имеет (иван, машина) сопоставляется с имеет (иван, Х) X=машина
[1,2] не сопоставляется [3, X]
[X,Y,Z] сопоставляется [петя, вася, нина] X= петя, Y = вася, Z = нина
Кроме унификации в Прологе ,естественно, имеются аналогичные обычным арифметические операции, операции сравнения, вводавывода и т.д. Однако применяются они несколько другим отличным от принятого в алгоритмических языках образом, т.к. опять же реализуются как предикаты. В частности, знак „=‟ фактически представляет собой инфиксный предикат.
Примеры унификации :
Выражение |
Результат |
|
X = 3+3 |
X=6 |
|
X = “3” + “3” |
Неверный тип |
Это ошибка |
X = 4 + x |
Неверный тип тип |
Это ошибка |
X = X+1 |
Свободная переменная в выражении |
|
[a,X,Y]=[a,b,c] |
X=b , Y=c |
|
[Z,u,D]=[x,y,z] |
No |
Это результат |
[X|Y]=[a,b,c] |
X=a , Y=[“b”, “c”] |
|
L=[a,b,c,d],L1=[1|L] |
L=[a,b,c,d] , L1=[1,a,b,c,d] |
|
Основными утверждениями (clauses) Пролога являются факт и правило. Отличительной чертой утверждения является точка в конце.
5
Факт - это предикат, завершенный символом "точка".
Факты описывают свойства объектов и отношения между объектами.
Свойства |
Отношения |
собака (бобик). |
владеет(иван,машина). |
человек (сократ). |
владеет(иван,юпитер). |
человек(Студент). |
любит(петя,оля). |
студент(петя). |
любит(Мальчик,Девочка). |
ест(_) |
является_родителем(Кто,_). |
|
|
На обычном языке эти утверждения будут выглядеть следующим образом:
Бобик – это собака. Сократ – это человек. Иван владеет машиной. Петя любит Олю
Особо следует выделить примеры в последней строке. Они будут звучать как: «Все едят» и «Все, кто является родителем». Автономно используемый символ подчеркивания „_‟ называется «анонимной переменной» и в утверждении показывает, что не имеет значения какой объект будет подставлен вместо соответствующего аргумента предиката.
Очевидно, что сам Пролог не может оценить достоверность тех или иных фактовнапример, вряд ли юпитер может принадлежать Ивану.
Правило - это конструкция вида «A: B, C, D.» , где A, B, C, D - предикаты.
A называется заголовком или целью, B, C, D - телом или подцелями. Цель правила – всегда единственна, число подцелей -произвольно.
Интерпретация правила выглядит следующим образом: A истинно, если одновременно истинны B, C и D.
Примеры правил:
имеет_собаку(Некто): имеет(Некто, Нечто), собака(Нечто).
имеет_стипендию(петров): экзамен(петров, Оценка), удовлетворительная(Оценка).
удовлетворительная(Оценка): Оценка >=3.
Здесь связка „:-„ может читаться как «если (if)» и трактоваться как аналог условного оператора из традиционных ЯП.
Символ “запятая” означает коньюнкцию подцелей (логическая операция “И”), “точка с запятой” - дизъюнкцию (логическая операция “ИЛИ”). Например, последний пример можно переписать следующим образом:
удовлетворительная(Оценка): Оценка =3; Оценка=4; Оценка=5.
Синтаксически между фактом и правилом нет никакой разницы. Факт - это правило, тело которого всегда истинно.
Совокупность всех утверждений программы обычно называется базой данных Проло-
га.
Утверждения записываются в секции CLAUSES.
Если мы хотим динамически (в процессе выполнения программы) менять используемую базу данных Пролога, т.е. добавлять, удалять, заменять факты, то соответствующие этим фактам предикаты должны быть описаны не в секции PREDICATES, а в секции FACTS ( или DATABASE). При этом динамически можно работать только с фактами, но не правилами.
6
Процедура - это множество правил с одной и той же головой (целью)
Т.е. должны совпадать имя и арность структуры, которая является целью. Причем все эти правила должны быть записаны последовательно.
В отличие от традиционных ЯВУ процедура Пролога представляет собой не описание последовательности действий, а скорее определение некоторого понятия.
Пример процедуры:
является_элементом(X,[Первый|Z]): X = Первый; является_элементом (X, Z).
В этом примере показана именно процедура, т.к. его можно переписать следующим образом:
Пример:
является_элементом(X,[Первый|Z]): X = Первый. является_элементом(X,[Первый|Z]): является_элементом (X, Z).
Выполнение Visual Prolog программы начинается тогда, когда в ее тексте встречается секция GOAL следующего вида:
GOAL A,B,C.
и представляет собой доказательство истинности некоторого определенного подцелями А,B,C (их число не ограничено) утверждения в рамках имеющейся базы данных (т.е. совокупности фактов и правил). Подцели могут иметь простую или составную структуру.
Пример целевого запроса:
GOAL является_элементом(3,[1,3,5,7]). да
В рассмотренных примерах Пролог только подтверждает/отрицает истинность целевого запроса. Для того чтобы узнать, при каких значениях, этот запрос будет истинным, в него надо ввести переменную.
Пример: DOMAINS
человек=symbol |
|
существо=symbol |
|
PREDICATES |
|
любит (человек,существо) |
|
CLAUSES |
|
любит (миша, cat). |
|
GOAL |
|
любит ("миша", Что). |
|
Что=cat |
(ответ Пролога) |
1 решение |
|
Теперь добавим в программу еще один факт: любит ("миша", "собака").
В результате получим сообщение об ошибке: «Решение неоднозначно».
Таким образом мы столкнулись с еще одной особенностью Пролога – он может найти не только одно, а все множество возможных решений исходной задачи. Однако, в нашем примере, чтобы помочь Прологу сделать это, надо указать, что предикат likes допускает неоднозначность.
7
Пример:
DOMAINS
человек=symbol существо=symbol
PREDICATES
nondeterm любит (человек,существо)
Clauses
любит (миша, cat). |
|
любит ("миша", "собака"). |
|
GOAL |
|
любит ("миша", X). |
|
X=cat |
(ответ Пролога) |
X=собака |
|
2 решения |
|
СТРУКТУРА ПРОГРАММЫ НА ПРОЛОГЕ
Программа на языке ПРОЛОГ включает следующие основные разделы:
описание имен и структур объектов (domains);
описание предикатов – названий отношений, существующих между объектами
(predicates);
раздел целевых утверждений (goal), который может отсутствовать; в этом случае программа будет запрашивать целевое утверждение при запуске;
описание фактов и правил, описывающих отношения (clauses).
Имена объектов (констант) в ПРОЛОГе пишутся с маленькой буквы, а переменных – с большой.
Рассмотрим, как можно описать на ПРОЛОГе задачу из некоторой предметной области, например географии.
Программа 1
DOMAINS
gorod, strana = symbol PREDICATES
situ(gorod,strana) CLAUSES
situ (london, england). situ (petersburg, russia). situ (kiev, ukraine). situ (pekin, asia).
situ (warszawa, poland). situ (berlin, europe).
situ (X, europe):- situ (X, russia). situ (X, europe):- situ (X, poland).
Выражение
situ(kiev, ukraine)
описывает тот факт, что город Киев находится на Украине. Ранее в программе был введен соответствующий предикат, работающий с объектами символьного типа. Название города и страны здесь являются константами, поэтому по правилам ПРОЛОГа их нужно писать с маленькой буквы. Вместо блока определений:
8
DOMAINS
gorod, strana = symbol PREDICATES
situ(gorod,strana)
можно было просто описать предикат:
PREDICATES
situ(symbol, symbol)
Иногда первый вариант предпочтительнее, поскольку позволяет оценивать семантический смысл аргументов предиката.
Вконце раздела clauses Программы 1 описаны два правила. Правило задает новый предикат через предикаты, определенные ранее. Правило состоит из головы (предиката) и тела – последовательности предикатов. Голова отделяется от тела значком :- , который можно интерпретировать как слово «Если». Таким образом, заключение является головой правила, а тело правила состоит из набора посылок.
Использование правил является основным способом представления знаний в интеллектуальных системах.
Смысл правила состоит в том, что цель, являющаяся головой, будет истинной, если интерпретатор ПРОЛОГа сможет показать, что все выражения (подцели) в теле правила являются истинными.
Вправилах буква X (или любая другая заглавная буква, или любое слово, начинающееся с заглавной буквы) обозначает переменную, которая может принимать разные значения.
Так, правило
situ (X, europe):- situ (X, poland)
означает, что любой польский город является одновременно европейским городом. Добавлением новых правил можно пополнять и модифицировать описание задачи. Если мы хотим описать тот факт, что все города Франции являются одновременно европейскими городами, то достаточно добавить всего одно правило
situ (X, europe):- situ (X, france)
иможно будет по-прежнему использовать все остальные факты о городах Европы.
ВПРОЛОГе можно использовать составные объекты. Составные объекты позволяют описывать иерархические структуры, в которых описание одного предиката включает в себя описание других предикатов.
Например:
Программа 2
DOMAINS personal_library=book(title,author,publication) publication= publication(publisher,year) collector,title,author,publisher=symbol year=integer
PREDICATES
collection(collector, personal_library) CLAUSES
9
collection(“Иванов”,book(“Война и мир”, “Лев Толстой”, publication(“Просвещение”,1990))).
При описании правил часто возникает необходимость использовать логические связки И и ИЛИ. В качестве связки И используется запятая, а в качестве связки ИЛИ – точка с запятой. Например:
gigant(X) :- rost(X,Y),Y>200. star_or_mlad(X) :- X>70; X<10.
ПРОЛОГ имеет большое количество встроенных предикатов, т.е предикаты, определяемые автоматически. Например, встроенный предикат nl вызывает перевод строки, а встроенный предикат write применяется для вывода информации на экран. Встроенные предикаты используются так же, как и определяемые пользователем предикаты, но встроенный предикат не может являться головой правила или появляться в факте.
Часто используемыми встроенными предикатами являются = (унификация) и логическое отрицание not. Например:
student(X) :- X=”Петров”; X=”Иванов”. xor_student(X) :- not(X=”Петров”), not(X=”Иванов”). planeta(X) :- not(X=”солнце”).
Утверждение not(X = Y) эквивалентно X<>Y.
Иногда бывает полезно использовать предикаты, про которые заранее известно, истинны они или ложны. Для этих целей используют предикаты true и fail. Предикат true всегда истинен, в то время как fail всегда ложен. Последний предикат используется для управления процессом решения задачи на ПРОЛОГе.
ПРОЛОГ-программа может использовать комментарии, которые не влияют на выполнение программы, но могут оказать помощь человеку, читающему программу. ПРОЛОГ игнорирует произвольное число строк, заключенное между символами /* и */. Все, что находится между % и концом строки, также рассматривается как комментарий:
/* Здесь записан комментарий */ % Это тоже комментарий
При описании конкретной предметной области обычно имеется набор исходных фактов и правдоподобных допущений, на основании которых формулируются правила.
Рассмотрим, каким образом на ПРОЛОГе можно описать задачу о семейных отношениях.
Пусть имеются факты об отцовстве:
1)Иван – отец Игоря.
2)Иван – отец Сидора.
3)Сидор – отец Лизы. Введем также три предиката:
Мужчина (x), означающий, что x – мужчина, Единокровный (x,y), означающий единокровность x и y, Брат (x,y), означающий, что x брат y.
Справедливы, очевидно, следующие правила:
1)«Все отцы – мужчины».
2)«Если у детей один отец, то они единокровны».
3)«Брат – это единокровный мужчина».
Рассмотрим вывод решения при ответе на вопрос:
10