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

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

.pdf
Скачиваний:
1
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
утверждения:
1. Если <t1,..., tk> - ответ, то каждый его частный случай, не содержащий переменных, есть правильный ответ.
2. Каждый правильный ответ <t1',..., tk'> на запрос Q является частным случаем некоторого ответа <t1,..., tk>, выдаваемого успешным вычислением Q.
Таким образом, пространство вычислений полно с точки зрения логики процедурной семантики.
Упражнения
1. Постройте для упражнения 3.6.1 дерево вычислений.
2. Постройте для упражнения 3.6.2 дерево вычислений.
3. Постройте для упражнения 3.6.3 дерево вычислений.
4. Постройте для упражнения 3.6.4 дерево вычислений.
5. Для упражнения 3.9.5 укажите множество интерпретаций прогрммы, множество моделей прогрммы и основную модель.
6. Для упражнения 3.9.5 укажите один из правильных ответов и ответ, не являющийся правильным.
Языки логического программированияВ.С. Рублев
91
Язык Пролог: стратегии вычислений и встроенные отношения
Стратегии вычислений: последовательные вычисления; стратегия в глубину и слева направо; проблема бесконечных ветвей; проблема большого перебора; правило отсечения и пример программы для базы знаний библиотеки; добавление спецификаций; стратегия в ширину и ее преимущество при бесконечных ветвях; параллельные вычисления и стратегии "или"-параллельности и "и"-параллельности. Встроенные отношения: встроенные отношения и предикаты; дополнительные функторы для операций отрицания и дизъюнкции.
Стратегии вычислений
Пространство вычислений чистого недетерминированного Пролога содержит пути всех возможных вычислений. Каждый интерпретатор Пролога (Пролог-машина) реализует какую-то стратегию обхода дерева вычислений для запроса. Стратегии могут быть последовательными и параллельными.
Последовательные вычисления.
Стратегия в глубину и слева направо. При использовании этой стратегии мы передвигаемся сверху вниз на правилах программы (упорядоченность правил каждой процедуры программы) и слева направо на атомах запроса. На каждом шаге вычислений считается самый левый атом запроса и к нему применяется самое первое правило соответствующей процедуры. В стеке запоминается возможное разветвление (для выбора следующего правила с тем же предикатным символом).
Если при вычислении обнаруживается тупик, то идет возврат к последнему разветвлению - backtracking (отменяются результаты подстановки после этого разветвления).
Если же получен ответ, то для продолжения получения других ответов также нужно выполнить backtracking. Именно эту стратегию мы использовали в примере 1 раздела 3.6.
Языки логического программированияВ.С. Рублев
92
Достоинством стратегии является простота, а недостаток - большой перебор. При наличии в дереве вычислений бесконечных ветвей интерпретатор зациклится. Среди средств преодоления этого недостатка
1. введение правила отсечения ;
2. добавление спецификаций.
Рассмотрим эти способы.
Использование правила отсечения связано с помещением в правую часть какого-либо правила оператора отсечения в виде знака '|' вертикальной черты. При его выполнении (когда он становится самым левым в запросе) забываются все разветвления до этого места и возврат производится только к последующим разветвлениям. Пусть, например, имеются правила:
P <- A, |, B P <- C.
Тогда при выполнении оператора отсечения забываются все разветвления при выполнении процедуры A и при выполнении второго правила.
Рассмотрим пример из книги Клоксина и Мелиша "Программирование на языке Пролог". Описывается база знаний библиотеки, которая определяет занятость книг читателями, отсутствие возврата читателем книги к сроку и услуги, предоставляемые для читателей. Услуги делятся на основные, к которым относится пользование каталогом и получение справок, и дополнительные, к которым относится пользование абонементом и межбиблиотечным абонементом. Дополнительные услуги не оказываются для читателей, которые имеют задолженность по возврату взятых книг. Некоторый запрос должен определить список услуг, предоставляемых каждому читателю. При составлении такого списка мы должны учитывать, что если читатель не возвратил хотя бы одну книгу, то не надо исследовать, какие книги он еще не возвратил, ­ему предоставляются только основные услуги. В этом случае мы и используем оператор отсечения:
Языки логического программированияВ.С. Рублев
93
книга (книга123456) <­книга (книга234567) <­книга (книга345678) <­. . . читатель ('Иванов') <­читатель ('Петров') <­читатель ('Сидоров'’) <­. . . книгаНеВозвращена ('Иванов', книга123456) <­книгаНеВозвращена ('Сидоров', книга234567) <­книгаНеВозвращена ('Иванов', книга345678) <­. . . оснУслуги (каталог) <­оснУслуги (справки) <­допУслуги (абонемент) <­допУслуги (межбиблАбонемент) <-
общУслуги (X)<- оснУслуги (X)
общУслуги (X) <- допУслуги (X) услуги (Читатель, ВидУслуг)<- читатель (Читатель), книгаНеВозвращена (Читатель, Книга), |, основныеУслуги (ВидУслуг)
услуги (Читатель, ВидУслуг) <- общУслуги (ВидУслуг)
При выполнении запроса
<- читатель (X), услуги (X, Y)
сначала отождествляется переменная X с читателем Иванов. Затем начинает выполняться второй атом запроса, который должен установить список услуг для данного читателя. При выполнении первого правила с предикатным символом услуги образуется новый запрос:
<- читатель ('Иванов'), книгаНеВозвращена ('Иванов', Книга), |, основныеУслуги (ВидУслуг)
Языки логического программированияВ.С. Рублев
94
Первый атом этого запроса отождествляется с фактом (удачное вычисление). При вычислении второго атома этого запроса будет сначала найден факт
книгаНеВозвращена ('Иванов', книга123456) <-, и так
как следующий атом запроса - оператор отсечения, то после вычисления всего запроса не будет возврата к поиску фактов невозвращения других книг Ивановым и переход к использованию других правил процедуры услуги. Результатом вычисления запроса для Иванова будет список только основных услуг.
При вычислении следующего запроса для Петрова, у которого все книги возвращены вовремя, вычисление запроса для первого правила процедуры услуги закончится неудачно, и вычисление запроса для второго правила этой процедуры приведет к появлению всех услуг для
Петрова.
При способе добавления спецификаций преодоления недостатка большого перебора в программу Пролога добавляются спецификации, влияющие на порядок вычислений (подсказки программиста интерпретатору, в каком порядке выгоднее применять правила или выделять атомы).
Стратегия в ширину. Она состоит в том, что обход дерева вычислений происходит в другом порядке: вниз на один уровень дерева, затем слева направо по всем дугам дерева (атомам и правилам процедуры для каждого атома), снова вниз на один уровень и т.д. При этом способе бесконечные ветви дерева вычислений не страшны, зацикливания не будет, если должно быть хотя бы одно успешное вычисление. В противном случае устанавливается порог в количестве LISP, при превышении которого следует отрицательный ответ на запрос.
Параллельные вычисления.
Различают 2 вида параллельности:
1. "или"-параллельность - параллельность применяется к выделенному атому запроса для всех правил с данным предикатным символом;
Языки логического программированияВ.С. Рублев
95
2. "и"-параллельность - параллельность применяется при обработке всех (или только некоторых) атомов запроса.
Встроенные отношения
Встроенные отношения предоставляются в готовом виде по соображениям удобства или невозможности определить их средствами чистого Пролога. Одни из них используются в виде запросов, выполнение которых приводит к определенным действиям. Некоторые из них приведены в табл. 10.1.
Таблица 10.1.
Запрос Описание действия
<- consult (<имя файла>)
Просматривает файл и добавляет из него правила в конец программы
<- reconsult (<имя файла>)
Вводимые из файла правила заменяют все правила до данного
<- var (X)
X является неконкретизированной
переменной
<- nonvar (X)
X не является неконкретизированной
переменной
<- term (X)
X – терм
<- integer (X) X – целое число
Другие встроенные предикаты могут использоваться в правилах программы. Они приведены в табл. 10.2.
Помимо этого используются функторы not для операции отрицания и точка с запятой ';' для обозначения операции дизъюнкции. Так, в примере
<- (not мать (X, Y); Y=ева), |, fail
вычисления запроса прекращаются, как только будет обнаружено, что Y интерпретируется как ева или для интерпретации Y имеется объект X, который не находится с Y в отношении мать.
Языки логического программированияВ.С. Рублев
96
Таблица 10.2.
Предикат Описание отношения
true всегда истинный
fail
всегда ложный
plus (X, Y, Z) X+Y=Z (для сложения и вычитания)
times (X, Y, Z)
X*Y=Z (для умножения и деления)
read (X)
читает терм с входного потока и сравнивает его с
X
write (X) печатает терм в выходной поток
Использование функтора not основано на следующем стандартном определении отношения not X ), где X - целевой предикат:
not X <- X,|,fail not X <-
В этой конструкции порядок правил программы фиксирорван и не зависит от стратегии (сначала идет правило с отсечением, а затем универсальный факт, и поиск подходящего правила идет только в этом порядке при любой стратегии. Так в вышеприведенном примере при вычислении предиката not мать( X1,Y1) он становится целевым
и рассматривается первое правило. При этом обрабатывается сначала предикат мать(X1,Y1), и если найдется интерпретация переменных
X1 и Y1, при которой этот предикат имеет истинное значение, то
последующее в теле правила отсечение приводит к омене всех разветвлений до этого места (т. е. второе правило не применяется) и значение определяется встроенным предикатом fail, имеющем всегда ложное значение. Если же такой интерпретации переменных X1 и Y1 не
найдется, то вычисления в силу ветвления в этой точке переходят ко второму правилу, которым является универсальный факт not X, что приводит к истинному значению предиката not мать (X1,Y1).
Упражнения
1. Постройте для программы упражнения 3.6.1 запрос на получение
Языки логического программированияВ.С. Рублев
97
всех программных кодов, каждый из которых не включает в себя ни один другой программный код, и для этого запроса постройте дерево вычислений.
2. Используя встроенные отношения, постройте программу на Прологе и запрос для вычисления наибольшего общего делителя любых двух заданных натуральных чисел.
3. Используя встроенные отношения, постройте программу на Прологе и запрос для вычисления целой неотрицательной степени целого числа.
Языки логического программированияВ.С. Рублев
98
Модель Бэкуса алгебры программ: основные конструкции
Общая характеристика модели Бэкуса. Базис модели Бэкуса: атомы и примитивные функции как скалярные типы; объекты и формы как структурные типы; атомы и кортежи; неопределенность; примеры функций. Примитивные функции Пролога: условное выражение Маккарти и синтаксис описания функций; логические функции; арифметические операции и отношения; функции кортежей; функции логических операций.
Общая характеристика модели Бэкуса
В 1978 году выдающийся американский информатик Дж. Бэкус, создатель первых языков программирования ФОРТРАН и АЛГОЛ, в докладе при вручении ему высшей премии по информатике - премии Алана Тьюринга - выдвинул модель алгебры программ. Эта модель является развитием идей языка Рефал в направлении введения форм ­структур более мощных, чем функции.
Формы являются функциями высших порядков: если аргументами функции являются данные, то аргументами формы являются функции. Таким образом форма есть алгоритм (программа), который преобразует другой алгоритм (программу). Эта фундаментальная идея позволяет ввести алгебру форм, которая и является алгеброй программ.
Примеры форм известны из математических курсов:
1. Определенный интеграл есть форма, которая функции ставит в соответствие число.
2. Неопределенный интеграл есть форма, которая функции ставит в соответствие другую функцию (вернее даже - некоторое множество других функций).
3. Производная есть форма, которая одной функции ставит в соответствие другую функцию.
Заметим, что в Рефале есть одна форма apply, которая названа функцией порождения процесса (в модели Бэкуса она называется
Языки логического программированияВ.С. Рублев
99
аппликацией). Аргументом этой формы является функциональный терм (другая функция), а значением этой формы - применение функции аргумента к своим данным, т. е. результат выполнения функционального терма.
В модели Бэкуса форма аппликации является фундаментальной наряду с еще 8 формами. Все другие формы строятся из комбинации фундаментальных, а в основу алгебры программ положены как аксиомы алгебраические законы тождества некоторых форм.
Отметим также, что под влиянием этой новой для языков программирования идеи форм в других языках программирования также стали вводиться конструкции форм. Так, например, в языке C++ Б.Страуструп ввел новую конструкцию, названную им алгоритмами, которые фактически являются формами.
Базис модели Бэкуса
В модели Бэкуса определяются 2 скалярных типа:
атом - для данных;
примитивная функция - для программ
и 2 структурных типа:
объект - для данных; конструируется из атомов;
формы - для программ; с их помощью создаются новые функции.
Атомами являются идентификаторы, числа, специальные знаки T и F, а также пустой кортеж, обозначаемый <>.
Объект - это атом или кортеж
<x1,..., xn>,
где - либо объект, либо неопределенность, которая изображается как <?>. Примеры объектов: 15, <AB, 1, 2>, <a,
Языки логического программированияВ.С. Рублев
100
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]