Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Языки логического программирования. Учебное пособие

.pdf
Скачиваний:
1
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
. В одном из упражнений предлагается написать такой
алгоритм на Рефале-5.
Блок
Другой структурирующей конструкцией Рефала-5 является блок. Он используется в тех случаях, когда несколько рядом стоящих предложений начинаются с одинаковых образцов, либо с одинаковых условий, либо с одинаковых левых частей условий. Такие группы можно объединять в блоки, вынося общее начало "за скобки". Это преобразование может изменить смысл программы. Поэтому следует обратить внимание на семантику блока, которая определяется ниже.
Рассмотрим в качестве примера функцию Merge слияния двух упорядоченных последовательностей в одну упорядоченную последовательность. Используемая при этом функция Compare сравнивает первые термы исходных последовательностей и результатом выдает символ '<', если терм первой последовательности меньше терма второй последовательности; символ '=', если термы равны; и символ '>', если терм первой последовательности больше. Функция Compare используется в условии функции Merge.
Merge { (tA e1)(tB e2), <Compare (tA tB)> : '<' = tA <Merge (e1) (tB e2)>; (tA e1)(tB e2), <Compare (tA tB)> : '=' = tA tB <Merge (e1) (e2)>; (tA e1)(tB e2), <Compare (tA tB)> : '>' = tB <Merge (tA e1) (e2)>; (e1)(e2) = e1 e2; }
В этом примере первые 3 рефал-предложения функции Merge начинаются с одинаковых образцов и одинаковых левых частей условий. Их можно вынести за фигурные скобки блока, оставив в блоке результатные окончания этих предложений.
В общем случае при исполнении блок заменяется на одно из входящих в
Языки логического программированияВ.С. Рублев
61
него окончаний. Вначале делается попытка использовать первое окончание. Но если его исполнение завершается неуспехом, то выбирается второе, и т.д. Если же последнее окончание блока оканчивается неуспехом, то весь блок оканчивается аварийно (в Рефале-6 - неуспехом).
При использовании конструкции блока программа функции Merge станет более наглядной:
Merge { (tA e1)(tB e2), <Compare (tA tB)> : { '<' = tA <Merge (e1) (tB e2)>; '=' = tA tB <Merge (e1) (e2)>; '>' = tB <Merge (tA e1) (e2)>; } (e1)(e2) = e1 e2; }
В общем случае образцовым окончанием называется окончание предложения, начинающееся с образца условия, а последовательность образцовых окончаний, заключенную в фигурные скобки, назовем образцовым блоком . Заметим, что тело функции всегда является образцовым блоком. Для полноты картины в качестве тела функции будем допускать не только блок, но и образцовое окончание, т. е. наружные фигурные скобки могут опускаться, если тело состоит из одного окончания.
В описанном примере мы выделили образцовый блок, который этой структурой не только сделал программу более наглядной, но и сделал ее более эффективной - результатная часть условия вычисляется лишь 1 раз, а затем по очереди сравнивается с образцами образцового блока.
По аналогии с образцовым окончанием и образцовым блоком вводятся результатное окончание и результатный блок. Результатным окончанием называется окончание рефал-предложения, начинающееся с результатного выражения, входящего в условие, а результатным блоком называется последовательность результатных окончаний, заключенная в фигурные скобки. Результатный блок следует применять, когда образцы рефал-предложений одинаковые, а результатные выражения их условий
- разные.
Языки логического программированияВ.С. Рублев
62
Рассмотрим пример определения функции Compset , которая сравнивает 2 множества на включение и возвращает в качестве результата символ '<', если первое множество включено во второе, символ '>', если первое множество включает второе, и символ '?', если ни одно из множеств не включено в другое. При описании будем использовать функцию Diff, которая определяет разность 2 множеств
- множество из элементов, входящих в первое множество и не входящих во второе множество. Функцию Compset можно описать следующим образом:
Compset { (e1) (e2) , <Diff (e1) (e2)> : = '<'; (e1) (e2) , <Diff (e2) (e1)> : = '>'; (e1) (e2) , : = '?'; }
Все 3 рефал-предложения имеют одинаковые образцы, но результатные части условий у них разные (в третьем предложении оно пустое). Что касается правых образцовых частей условий, то они во всех предложениях пустые. Условие первого предложения выполняется, если разность первого и второго множества пустая, т. е. первое множество включено во второе. Условие второго предложения выполняется, когда второе множество включено в первое. Наконец, условие третьего предложения всегда выполняется: пустой результат сопоставляется с пустым образцом. Так как условия разные, то можно образовать результатный блок, вынеся общий образец всех трех предложений за скобки:
Compset (e1) (e2) , { <Diff (e1) (e2)> : = '<'; <Diff (e2) (e1)> : = '>'; : = '?'; }
Упражнения
1. Разработайте программу на Рефале-5 для задачи о назначениях из
раздела 2.17.2 с трудоемкостью алгоритма .
Языки логического программированияВ.С. Рублев
63
2. Разработайте программу Diff на Рефале-5, определяющую разность 2 множеств термов.
3. Разработайте программу на Рефале-5 объединения 2 множеств термов.
4. Разработайте программу на Рефале-5 пересечения 2 множеств термов.
5. Разработайте программу на Рефале-5 сравнения 2 термов, возвращающую один из символов '<', '=' или '>' в зависимости от данных (для чисел - обычное сравнение, для цепочек символов и других термов - лексикографическое сравнение).
1)
Это определение в дальнейшем будет дополнено конструкцией с
образцовым блоком.
Языки логического программированияВ.С. Рублев
64
Язык ПРОЛОГ: основные конструкции
Общая характеристика языка Пролог: базы знаний и экспертные системы. Объекты и термы Пролога: объекты Пролога - имена, переменные и списки; основные и неосновные термы; атомы. Факты Пролога: синтаксис фактов; универсальные факты. Правила Пролога: проблема недостаточности фактов для описания базы знаний; синтаксис правила - заголовок и тело правила; процедура как объединение правил с одним заголовком; программа Пролога как совокупность фактов и правил. Запросы Пролога: синтаксис запроса; ответ на запрос без переменных; запрос с переменными и интерпретация переменных при выполнении программы; примеры программ с запросами для них.
Общая характеристика языка Пролог
Математическая логика дает нам ясный и точный язык для явного выражения знаний, гипотез и целей. Возможность машинного доказательства теорем, основанного на специальном выводе, названном принципом резолюций, впервые была получена Дж. Робинсон в 1965 году. Это привело к желанию построить язык программирования, который позволил бы реализовать одну из интеллектуальных сторон деятельности человека - проведение рассуждений в виде программ.
В начале 70-х годов прошлого века группой под руководством А. Колмероэ в Марселе на Фортране была написана программа для доказательства теорем, названная Прологом (от Programmation en Logique). Это привело в конце десятилетия к разработке языка Пролог и в дальнейшем развитию этого языка и в целом направления, которое получило название логического программирования.
Язык Пролог близок к модели Маркова: также основой является поиск подходящей подстановки - интерпретация переменных . Но подстановки ищутся в правилах языка (аналог рефал-предложений), и целью является именно поиск подстановки.
Программа на Прологе состоит из правил, которые представляют собой продукции с предикатами (относительно объектов) в левой и правой части. Тем самым программа Пролога выражает некоторые знания о
Языки логического программированияВ.С. Рублев
65
внешнем мире (задаче или группе задач), необходимые для решения задач. Правила, не содержащие посылки в продукции, называются фактами , а вся система правил программы образует базу знаний .
Вопрос задачи, называемый запросом, - это также некоторый предикат, истинностью которого мы интересуемся. Если запрос не содержит переменных, то вычисление его значения дает ответ "Да" при его истинности либо ответ "Нет" при его ложности. Если же в предикате запроса есть переменные, то ищутся их значения ( интерпретация ), при которых этот предикат и все предикаты программы становятся истинными. В этом и состоят вычисления программы на Прологе.
Так как каждый предикат - это функция, то Пролог является языком функционального программирования.
Итак, в языке Пролог рассматриваются объекты и 3 вида утверждений относительно объектов: факты, правила и запросы. Единственной структурой данных является терм.
Объекты и термы Пролога
Объектами Пролога являются
имена (начинаются со строчной буквы), строки символов (заключаются в апострофы) и числа - константные объекты или константы; например, автомобиль, дом, иван, 'a+b', 'X', 123; переменные - могут принимать значения других объектов, и мы их будем писать прописными латинскими буквами: например, X,
A, W ;
списки - их элементами являются любые объекты; списки мы заключаем в квадратные скобки, разделяя элементы запятыми; например, [] - пустой список (он является константой, мы его будем обозначать также nil и любой список завершать этим элементом, чтобы показать конец списка), [a, b, c, nil] ­список, состоящий из трех констант a, b и c ; [X, [b, Y,
'X', nil], nil] - список, состоящий из двух элементов,
первый из которых - переменная X, а второй - список из трех элементов: имени b, переменной Y и строки 'X'.
Языки логического программированияВ.С. Рублев
66
Завершающий список элемент nil можно при записи опускать, подразумевая его в необходимых случаях. Для конкатенации (соединения) списков и элементов в один список используется точка как бинарная операция соединения левой части (головы списка) и правой части (хвоста списка). В случае операции конкатенации квадратные скобки на нулевом уровне можно опускать. Например, a.X.Y.a при
X=b, Y=c есть список [a, b, c, a], также при X=[b], Y=[c]
есть тот же список, а при X=[b, [d, e]] и Y=[[c]] есть список
[a, b, [d, e], [c], a].
Теперь индуктивно введем понятие терма. Термами являются объекты Пролога. Кроме того, термами являются составные термы. Составной терм образуется из имени функции и списка аргументов (термов Пролога) в круглых скобках. Синтаксически составной терм имеет вид
f(t1,..., tn),
где f - имя n -арного функтора, а - аргументы.
Примерами составных термов являются: холодный (вода), отец
(иван, петр), list(d, list(b, nil)) и bintree(bintree(nil, 7, nil), L, 12).
В первом примере составным термом является высказывание с именем булевой функции 1 аргумента-константы, которое имеет логическое значение истина или ложь.
Во втором примере отношение "иван является отцом петра" задается как булева функция с 2 аргументами-константами.
В третьем примере бинарная функция с именем list и двумя аргументами имеет в качестве первого аргумента константный объект d , а в качестве второго аргумента - составной терм с именем той же функции и возвращает, по-видимому, список.
В четвертом примере функция с именем bintree и тремя аргументами возвращает в виде списков бинарное дерево с корнем 7, правым сыном 12 и левым сыном, который определяется переменной L.
Языки логического программированияВ.С. Рублев
67
Термы, в которые не входят переменные, назовем основными , а термы, содержащие переменные, - неосновными . Так, три первых примера выше являются основными термами, а четвертый пример - неосновным термом.
В логическом программировании основной структурой является предикатная функция, описываемая составным термом, которая имеет истинностное значение (истина или ложь), возможно зависящее от значений аргументов. Такой предикат называется атомарным, или атомом .
Факты
Факты - это простейшие утверждения относительно объектов программы, которые считаются истинными, т. е. имеют смысл аксиом программы. Каждый факт оформляется в виде атомарного предиката и стрелки влево, которая находится справа от него. Так, в следующем примере
мужчина (иван)<­мужчина (петр)<­отец (иван, петр)<­произведение (2, 2, 4)<-
задается, что объекты иван и петр являются мужчинами, что иван является отцом петра и что дважды два - четыре.
Почему ставится стрелка? Общий вид записи продукции "если A, то B ", где A и B - предикаты, выражается на Прологе следующим образом:
B <- A.
Факт не имеет посылки и читается "то B ", т. е. утверждение B рассматривается как истинный факт.
Множество фактов образуют простейшую программу Пролога. Но атомарный предикат факта может содержать переменные в качестве аргументов или неосновные термы. В этом случае по умолчанию считается, что добавлен квантор всеобщности с переменными
Языки логического программированияВ.С. Рублев
68
предиката. Такие факты называются универсальными: они истинны для любых значений переменных. Например,
любит (X, яблоко)<-
означает, что любой объект программы "любит яблоко". Универсальные факты сокращают запись программы.
Правила
Хотя универсальные факты могут сократить запись, но все же использование только этого приема не всегда позволяет создать обозримую базу знаний либо в принципе не позволяет ее создать.
Приведем следующий пример. Необходимо создать базу знаний для определенного круга лиц, которая могла бы выразить родственные их связи. Рассмотрим естественный путь, при котором задаются отношения отец, мать, дочь, сын. С одной стороны, эти отношения могут оказаться избыточными или вести к серьезным логическим ошибкам из-за того, что некоторые факты не введены. Скажем, у двух лиц есть отношение отец, но нет симметричного отношения сын. С другой стороны, очень непросто написать предикаты для установления родства между любыми двумя лицами при таком задании фактов. Казалось бы, выход может быть найден, если ввести другие отношения, например, брат, сестра, кузен,
кузина, дедушка, бабушка, внук, внучка. Но и в этом
случае корректность программы (совокупности фактов) в связи с большой избыточностью будет трудно проверять, а проблемы с простым установлением родства двух любых лиц останутся.
Выходом может быть введение помимо двух отношений отец и мать отношения предок, частным случаем которого являются первые 2 отношения. В результате для выявления родства между любыми двумя лицами достаточно написать предикат, который устанавливает, является ли одно из лиц предком другого либо имеется ли у этих лиц общий предок. Это значительно проще, но надо ввести помимо фактов для отношений отец и мать правило, которое позволяет ввести отношение предок и в то же время не заставляет описывать
Языки логического программированияВ.С. Рублев
69
дополнительные факты для этого отношения.
Правило Пролога есть продукция, посылкой которой является конъюнкция атомарных предикатов, а заключением - 1 атомарный предикат. Правило имеет следующий синтаксис:
A <- B1,..., Bm (m >= 0),
где - атомарные предикаты и запятая в правой части правила означает конъюнкцию. Читать правило нужно так: "Если B1 и
B2 и т.д. и Bm, то A." Нетрудно видеть, что факт Пролога есть правило с
пустой правой частью ( m=0 ). Левая часть правила называется его заголовком, а правая часть - телом правила . Совокупность правил с одним и тем же предикатом в заголовке называется процедурой .
Решение вышеописанного примера состоит в определении отношения предок следующим образом: предком лица является либо мать, либо отец, либо мать предка, либо отец предка. Таким образом все решение сводится к следующей процедуре из 4 правил:
предок (X, Y) <- мать (X, Y) предок (X, Y) <- отец (X, Y) предок (X, Y) <- предок (Z, Y), мать (X, Z) предок (X, Y) <- предок (Z, Y), отец (X, Z)
Заметим, что отношение предок определено этими правилами рекурсивно. Теперь для определения родства между двумя лицами достаточно также задать рекурсивно отношение родственники следующей процедурой из 3 правил:
родственники (X, Y) <- предок (X, Y) родственники (X, Y) <- предок (Y, X) родственники (X, Y) <- предок (Z, X), предок (Z, Y)
Заметим, что обозначения переменных в правилах несущественны, лишь бы они обозначались одинаково в заголовке и теле процедуры. Но если на все переменные левой части подразумевается наложенным
квантор всеобщности то на все переменные правой части, которые отсутствуют в левой, подразумевается наложенным квантор
Языки логического программированияВ.С. Рублев
70
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]