- •У.Клоксин, к.Меллиш программирование на языке пролог Для программистов и пользователей эвм. Предисловие редакторов перевода
- •Предисловие ко второму изданию
- •Предисловие к первому изданию
- •Глава 1 введение
- •1.1. Факты
- •1.2. Вопросы
- •1.3. Переменные
- •1.4. Конъюнкции
- •1.5. Правила
- •1.6. Заключение и упражнения
- •Глава 2 более детальное описание
- •2.1. Синтаксические правила
- •2.1.1. Константы
- •2.1.2. Переменные
- •2.1.3. Структуры
- •2.2. Литеры
- •2.3. Операторы
- •2.4. Равенство и установление соответствия
- •2.5. Арифметика
- •2.6. Общая схема согласования целевых утверждений
- •2.6.1. Успешное доказательство конъюнкции целевых утверждений
- •2.6.2. Рассмотрение целевых утверждений при использовании механизма возврата
- •2.6.3. Установление соответствия
- •Глава 3. Использование структур данных
- •3.1. Структуры и деревья
- •3.2. Списки
- •3.3. Принадлежность элементов списку
- •3.4. Пример: преобразование предложений
- •3.5. Пример: упорядочение по алфавиту
- •3.6. Использование предиката присоединить и спецификация деталей
- •Глава 4. Возврат и отсечение
- •4.1. Порождение множественных решений
- •4.2. Отсечение
- •4.3. Общие случаи использования отсечения
- •4.3.1. Подтверждение правильности выбора правила
- •4.3.2. Комбинация «отсечение-fail»
- •4.4. Проблемы, связанные с использованием отсечения
- •Глава 5 ввод и вывод
- •5.1. Ввод и вывод термов
- •5.1.1. Вывод термов
- •5.1.2. Ввод термов
- •5.2. Ввод и вывод литер
- •5.2.1. Вывод литер
- •5.2.2. Ввод литер
- •5.3. Ввод предложений
- •5.4. Чтение файлов и запись в файлы
- •5.4.1. Запись в файлы
- •5.4.2. Чтение файлов
- •5.4.3. Ввод программ
- •5.5. Объявление операторов
- •Глава 6. Встроенные предикаты
- •6.1. Ввод новых утверждений
- •Списковая форма записи
- •6.2. Выполнение и невыполнение целевого утверждения
- •6.3. Классификация термов
- •6.4. Работа с утверждениями как с термами
- •6.5. Создание структур и работа с компонентами структур
- •6.6. Воздействие на процесс возврата
- •Отсечение
- •6.7. Формирование составных целевых утверждений
- •Конъюнкция целей
- •Дизъюнкция целей
- •6.8. Равенство
- •6.9. Ввод и вывод данных
- •6.10. Обработка файлов
- •6.11. Вычисление арифметических выражений
- •6.12. Сравнение чисел
- •6.13. Наблюдение за выполнением программы на Прологе
- •Глава 7. Еще несколько примеров программ
- •7.1. Словарь в виде упорядоченного дерева
- •7.2. Поиск в лабиринте
- •7.3. Ханойские башни
- •7.4. Справочник комплектующих деталей
- •7.5. Обработка списков
- •7.6. Представление и обработка множеств
- •7.7. Сортировка
- •7.8. Использование базы данных: random, генатом, найтивсе
- •Генератор случайных чисел (random)
- •Генератор имен (генатом)
- •Генератор списков структур (найтивсе)
- •7.9. Поиск по графу
- •7.10. Просеивай Двойки, Просеивай Тройки
- •7.11. Символьное дифференцирование
- •7.12. Отображение структур и преобразование деревьев
- •7.13. Применение предикатов clause и retract
- •Глава 8. Отладка пролог-программ
- •8.1. Расположение текстов программ
- •8.2. Типичные ошибки
- •8.3. Модель трассировки
- •8.4. Трассировка и контрольные точки
- •Выдача информации о цели
- •Выдача информации о предшественниках
- •Изменение уровня трассировки
- •Вмешательство в процесс согласования цели
- •Другие команды
- •Заключение
- •8.5. Фиксация ошибок
- •Глава 9. Использование грамматических правил в прологе
- •9.1. Проблема синтаксического анализа
- •9.2. Описание синтаксического анализа на языке Пролог
- •9.3. Запись грамматических правил в Прологе
- •9.4. Присоединение дополнительных аргументов
- •9.5. Введение дополнительных условий
- •9.6. Заключение
- •Глава 10. Пролог и математическая логика
- •10.1. Краткое введение в исчисление предикатов
- •10.2. Приведение формул к стандартной форме
- •Этап 1 - исключение импликаций и зквивалентностей
- •Этап 2 - перенос отрицания внутрь формулы
- •Этап 3 - сколемизация
- •Этап 4 - вынесение кванторов общности в начало формулы
- •Этап 5 - использование дистрибутивных законов для & и #
- •Этап 6 - выделение множества дизъюнктов
- •10.3. Форма записи дизъюнктов
- •10.4. Принцип резолюций и доказательство теорем
- •10.5. Хорновские дизъюнкты
- •10.6. Пролог
- •10.7. Пролог и логическое программирование
- •Глава 11. Программные проекты на прологе
- •11.1. Простые проекты
- •11.2. Более сложные проекты
- •Приложение а. Ответы к некоторым упражнениям
- •Приложение в. Программа приведения формул исчисления предикатов к стандартной форме
- •Этап 1 - исключение импликаций
- •Этап 2 - перенос отрицания внутрь формулы
- •Этап 3 - сколемизация
- •Этап 4 - вынесение кванторов общности в начало формулы
- •Этап 5 - использование дистрибутивных законов для. & и #
- •Этап 6 - выделение множества дизъюнктов
- •Печать утверждений
- •Приложение с. Различные версии языка пролог
- •Синтаксис
- •Различные ограничения
- •Возможности окружения
- •Компиляция
- •Специальные встроенные предикаты
- •Средства отладки
- •Приложение d. Пролог для эвм dec system-10
- •Пример сеанса работы
- •Синтаксис
- •Различные ограничения
- •Возможности окружения
- •Компиляция
- •Различия во встроенных предикатах
- •Дополнительные встроенные предикаты
- •Средства отладки
- •Литература
- •Приложение е. Микро-пролог
- •Пример сеанса работы
- •Синтаксис
- •Различные ограничения
- •Возможности окружения
- •Специальные встроенные предикаты
- •Средства отладки
- •Литература
- •Приложение f. Система мпролог[19]
- •Пример сеанса работы
- •Синтаксис
- •Модульность
- •Компоненты системы мПролог
- •Различные ограничения
- •Дополнительные встроенные предикаты
- •Средства отладки
- •Литература
- •Примечания
6.7. Формирование составных целевых утверждений
В правилах и вопросах вида X:-Y или ?-Y терм, появляющийся на месте Y, может состоять из единственного целевого утверждения либо представлять конъюнкцию целевых утверждений или их дизъюнкцию. Более того, можно употреблять в качестве целевых утверждений переменные и успешно доказывать согласованность целевого утверждения, когда целевое утверждение в действительности не согласуется, используя для этого предикат not. Предикаты, представленные в этом разделе, позволяют реализовать эти сложные способы выражения целевых утверждений.
Конъюнкция целей
Функтор ',' (запятая) определяет конъюнкцию целевых утверждений. Этот функтор был введен в гл. 1. Если X и Y – целевые утверждения, то целевое утверждение X, Y согласуется с базой данных, если согласуется X и Y. Если X согласуется и затем Y не согласуется, то делается попытка найти новое доказательство согласованности для X. Если X не согласуется, то не согласуется и конъюнкция в целом. Это и составляет суть механизма возврата. Функтор Y является встроенным и определен как левоассоциативный инфиксный оператор, так что X, Y, Z эквивалентно (X,Y),Z.
Дизъюнкция целей
Функтор ';' определяет дизъюнкцию (означающую или) целевых утверждений. Если X и Y – целевые утверждения, то целевое утверждение X; Y согласуется с базой данных, если согласуется X или Y. Если X не согласуется, то делается попытка доказать согласованность Y. Если и Y не согласуется, то не согласуется и дизъюнкция в целом. Мы можем использовать функтор ';' для того, чтобы выразить альтернативы в пределах одного утверждения. Например, будем считать, что некоторый объект является человеком, если этот объект – либо Адам либо Ева или если у объекта есть мать. Мы можем выразить это в одном правиле следующим образом:
человек(Х):- (Х=адам; Х = ева; мать(Х,Y)).
В этом правиле мы в действительности определили три альтернативы. Однако для Пролога это правило содержит две альтернативы, одна из которых сама содержит две альтернативы. Так как функтор ';' является встроенным и определен как правоассоциативный инфиксный оператор, то целевое утверждение в приведенном правиле в действительности можно переписать следующим образом:
';' (Х = адам, ';'(Х=ева,мать(Х, Y)))
Таким образом, первая возможность соответствует тому, что X – это адам. Вторая возможность включает две альтернативы: X это ева или у X есть мать
Мы можем использовать дизъюнкцию в любом месте, где может быть использовано любое другое целевое утверждение на Прологе. Однако целесообразно использовать дополнительные скобки, чтобы избежать недоразумений, касающихся взаимодействия операторов ';' и ','. Обычно мы можем избежать применения дизъюнкции путем использования нескольких фактов и правил, содержащих, возможно, определения некоторых дополнительных предикатов. Например, приведенный выше пример в точности эквивалентен следующему:
человек(адам).
человек(ева).
человек(Х):- мать(Х,Y).
Этот вариант более традиционен и, возможно, проще для чтения. Для многих Пролог-систем он может быть более эффективным по сравнению с использованием ';'.
Результатом отсечения является невозможность изменить выбор альтернатив, обусловленных наличием дизъюнкций, сделанный с момента сопоставления с правилом, содержащим отсечение (см. гл. 4). Вследствие этого имеется ряд случаев, когда программа, содержащая отсечения, не может быть преобразована в обычную программу без использования дизъюнкций. Однако в общем случае не рекомендуется чрезмерно часто использовать ';'. В качестве предостережения отсылаем вас к гл. 8, где показано, как необдуманное использование ';' затрудняет понимание программ.
call(X)
Предполагается, что X конкретизирован термом, который может быть интерпретирован как целевое утверждение. Целевое утверждение саll(X) считается согласованным, если попытка доказать согласованность X завершается успехом. Целевое утверждение call(X) не согласуется с базой данных, если попытка доказать согласованность X заканчивается неудачей. На первый взгляд этот предикат может показаться излишним, поскольку, естественно, возникает вопрос: почему аргумент call не может быть записан непосредственно как целевое утверждение? Например, целевое утверждение
…, саll(принадлежит(а,Х)),…
всегда может быть заменено следующим:
…, принадлежит(a,X),…
Однако если мы создаем целевые утверждения, используя предикат '=..' или ему подобные, то возможны обращения к целевым утверждениям, функторы которых неизвестны на момент ввода программы в Пролог-систему. Так, например, в определении предиката consult в разд. 7.13 нам надо иметь возможность рассматривать любой терм, прочитанный после ?-, как целевое утверждение. Предполагая, что Р, Х и Y конкретизированы функтором и аргументами соответственно, можно использовать call следующим образом:
…, Z =… [P,X,Y], call(Z),…
Последний фрагмент программы можно рассматривать как способ выражения обращения к целевому утверждению следующего вида:
…, P(X,Y),…
которое в рамках стандартной версии Пролога, рассматриваемой в этой книге, синтаксически некорректно. Однако некоторые версии языка Пролог допускают использование переменной в качестве функтора целевого утверждения.
not(X)
Предполагается, что X конкретизирован термом, который может быть интерпретирован как целевое утверждение. Целевое утверждение not(X) считается согласованным с базой данных, если попытка доказать согласованность Xзаканчивается неудачей. Целевое утверждение not(X) считается несогласованным, если попытка доказать согласованность X успешно завершается. В этом плане предикат not очень похож на call, за тем исключением, что согласованность или несогласованность аргумента, рассматриваемого как целевое утверждение, приводит к противоположному результату.
Чем отличаются следующие два вопроса?
/* 1 */?- принадлежит(Х,[а,b,с]), write(X).
/* 2 */?- not(not(принадлежит(Х,[а,b,с]))), write(X).
Может показаться, что между ними нет никакой разницы, так как в запросе 2 принадлежит(Х,[а,b,с,]) согласуется, поэтому not(принадлежит(Х,[а,b,с,])) не согласуется и not(not(принадлежит(Х,[а,b,с]))) согласуется. Это правильно лишь отчасти. В результате первого вопроса будет напечатан атом 'а', а в результате второго – неконкретизированная переменная. Рассмотрим, что происходит при попытке доказать согласованность первого целевого утверждения из второго вопроса:
1. Целевое утверждение принадлежит согласуется, и X конкретизируется значением а.
2 Предпринимается попытка доказать согласованность первого целевого утверждения not, которая заканчивается неудачей, так как целевое утверждение принадлежит, являющееся его аргументом, согласуется с базой данных. Теперь вспомним, что, когда целевое утверждение не согласуется, все конкретизированные переменные, такие как X в нашем примере, должны теперь «забыть», что они обозначали до сих пор. Следовательно, X становится неконкретизированной.
3. Предпринимается попытка доказать второе целевое утверждение not, и эта попытка заканчивается успехом, так как его аргумент (not(принадлежит(…))) не согласован. Переменная X остается неконкретизированной.
4. Предпринимается попытка выполнить целевое утверждение write с неконкретизированным значением X. И, как описано в разд. 6.9, неконкретизированные переменные печатаются специальным образом.
