- •Глава 1. Введение в пролог
- •1. Декларативные и процедурные языки программирования
- •2. Пролог и логика предикатов. Внешние цели
- •3. Управление программой. Подцели. Механизм сопоставления
- •4. Внутренние подпрограммы унификации
- •Глава 2. Внутренние цели. Механизм возврата
- •1. Структура пролог-программы
- •2. Использование внутренних целей
- •3. Встроенный предикат fail
- •4. Сокращенные варианты внутренних запросов
- •5. Использование в запросах анонимных переменных
- •6. Механизм возврата
- •Глава 3. Типы данных и арифметика Turbo Prolog
- •1. Стандартные типы данных
- •2. Структуры, простые и составные
- •3. Структурные диаграммы
- •4. Использование в запросах анонимных переменных
- •5. Использование альтернативных доменов
- •6. Арифметика в Turbo Prolog
- •Глава 4. Предикат отсечения (!). Программирование альтернатив. Правила повтора
- •1. Повторения и возвраты
- •2. Отсечение (!)
- •3. Программирование альтернатив
- •4. Правило повтора
- •Глава 5. Методы организации рекурсии
- •1. Простая рекурсия
- •2. Метод обобщенного правила рекурсии
- •3. Граничное условие рекурсии. Нисходящая и восходящая рекурсии
- •4. Программа о подсчете числа точек
- •Глава 6. Списки
- •1. Основные понятия
- •2. Списки и турбо-пролог
- •3. Атрибуты списка
- •4. Внутреннее представление списков
- •5. Применение списков в программе
- •6. Метод разделения списка на голову и хвост
- •7. Поиск элемента в списке
- •8. Присоединение списка
- •9. Добавление и удаление элемента
- •10. Подсписок
- •11. Перестановки списка
- •Глава 7. Сортировка списков
- •1. Разделение списка на два
- •2. Сортировка списков методом вставки
- •3. Быстрая сортировка
- •4. Быстрая сортировка_1
- •5. Компоновка данных в список
- •Глава 8. Программирование алгоритмов с возвратом. Представление графов в turbo prolog
- •1. Задача о весах
- •2. Представление графов в turbo prolog
- •3. Поиск пути на неориентированном графе
- •4. Поиск гамильтоновых циклов
- •5. Поиск пути минимальной стоимости
- •Глава 9. Динамическая база данных
- •1. Турбо-пролог и реляционные базы данных
- •2. Описание предикатов динамических бд
- •3. Встроенные предикаты asserta, assertz, retract, retractall, save, consult
- •4. Создание динамической базы данных
- •5. Обсуждение проекта базы данных
- •6. Создание базы данных
- •7. Написание программных модулей
- •Глава 10. Глобальные переменные в turbo prolog
- •1. Модификация базы данных
- •2. Накопление результатов с помощью вынуждаемого возврата
- •3. Подсчет членов парторганизации
- •4. Поиск пути минимальной стоимости от a до z
- •Библиографический список
- •Оглавление
3. Управление программой. Подцели. Механизм сопоставления
Для того, чтобы запустить программу на выполнение, нужно сформулировать цель. Цель состоит из взаимосвязанных предикатов. Пролог — система будет пытаться доказать цель, то есть логически вывести ее из имеющихся утверждений. Если цель состоит из конъюнкции предикатов (подцелей), то он будет доказывать подцели , выбирая их слева направо.
Если цель является фактом:
Goal: likes (mary, kiwi)
FALSE
Goal: likes (beth, apples)
TRUE
то ответ будет TRUE или FALSE.
Если цель содержит переменные, то Пролог выдаст или значения переменных, при которых цель истинна, или сообщение
No solutions (Нет решений)
Goal: likes (beth, X)
X= apples
Goal: likes(X, kiwi)
No solutions
Рассмотрим, как Пролог будет пытаться доказать цель «любит (бет, яблоки)» (рис 1.1).
Вначале Пролог будет пытаться сопоставить термы предиката цели и первого утверждения программы. Они сопоставимы. Затем сопоставляются термы объектов утверждения и цели. Сопоставление происходит слева направо. Объект «бет» цели несопоставим с объектом «мэри». Вся попытка сопоставить цель с первым утверждением неуспешна. Движемся слева направо — выбираем второе утверждение. Предикаты «любит» сопоставимы, объекты «бет» сопоставимы, при сопоставлении переменной X и объекта «яблоки», X получает значение «яблоки».
Переменная X стала СВЯЗАННОЙ или ОЗНАЧЕННОЙ.
Успешно сопоставив цель и голову правила «любит (бет, X)» с присвоением X значения «яблоки», Пролог переходит к доказательству тела правила, (голова правила будет истинна, если истинно тело). Для доказательства тела правила Пролог сам генерирует ПОДЦЕЛЬ «любит (мэри, яблоки)» и пытается ее доказать.
Сопоставление с первым фактом программы оказывается успешным, следовательно, успешно доказаны тело (и голова) правила и цель «любит (бет, яблоки)». Программа сообщит TRUE, хотя такого факта в программе в явном виде не было.
рис 1.1
Сопоставление — это процесс, проверяющий идентичность двух термов.
Если эти термы — константы или числа, то они сопоставимы, только когда они являются одним и тем же объектом.
Если один терм — константа, а другой — перемененная того же типа (в Турбо — Прологе каждый объект имеет строго определенный тип), то они сопоставимы, и переменная получает значение константы.
Два предиката сопоставимы, если:
имеют одинаковый предикатный терм (главный функтор),
одинаковую арность (число аргументов),
все их соответствующие компоненты сопоставимы.
Значения переменных определяются при сопоставлении компонент.
4. Внутренние подпрограммы унификации
Рассмотрим более подробно, как система ищет ответ на запрос.
Пусть наша программа пополнилась еще двумя фактами (программа 1.1):
любит (мэри, яблоки).
любит (мэри, апельсины).
любит (мэри, попкорн).
любит (бет, X):-
любит (мэри, X).
Goal: любит (мэри, X).
X — свободная (неозначенная) переменная, она не имеет значения. Она не равна 0, не равна пробелу, не равна ничему. Цель сопоставляется с первым фактом, X получает значение «яблоки». Цель доказана, Пролог выдает сообщение, что X=яблоки.
Затем X снова становится свободной переменной. Так как цель была внешней, то есть была задана после запуска программы, система будет искать все возможные решения. Поэтому цель сопоставится со вторым утверждением и X получит значение «апельсины» и будет напечатано второе решение. X снова станет свободной, цель сопоставится с третьим утверждением, будет найдено решение X=попкорн. Последнее утверждение и цель несопоставимы, поиск решений окончен.
В Прологе все переменные являются как бы локальными, значения им присваивают внутренние унификационные процедуры, и сохраняется оно только внутри данного утверждения.
Область известности (лексический диапазон) переменных — одно утверждение.
Поэтому одно и то же имя в двух разных предложениях обозначает две разных переменных.
Значение сохраняется переменной ровно до тех пор, пока:
— либо очередное сопоставление оказывается неуспешным, и вся цель несопоставимой;
— либо цель успешо вычислена.
/* Программа 1.1 «Любители морковки». Назначение:
демонстрация использованием внешней цели */
domains % описание типов объектов
% symbol — символическое имя
name, fruit = symbol
predicates
likes(name, fruit) % описание предикатов
clauses
likes(mary,apples).
likes(mary,oranges).
likes(mary,popcorn).
likes(ann,apples).
likes(beth,X):-
likes(mary,X).
likes(jonh,X):-
likes(mary,X),
likes(ann,X).
/* Конец программы */
Пример 1.2.
Генеалогическое древо имеет следующий вид (рис. 1.2)
рис.1.2
Опишем дерево с помощью отношений «родитель», «мужчина», «женщина».
родитель (том, боб). % Том — родитель Боба
мужчина (том).
женщина (пат).
Определим с помощью правил отношения «сестра», «отпрыск», «мать» (рис 1.3).
рис. 1.3
Упражнение 1.1.
По генеалогическому дереву (рис. 1.2) составить программу, включив в нее отношения «сестра», «отпрыск», «мать» (рис. 1.3).
Обратите внимание, как система отвечает на запрос
Goal: sister(X, Y). Отчего так происходит?
Опишем отношение предок(X,Z) (рис. 1.4).
рис 1.4
Для всех X и Z ,
X — предок Z, если
X — родитель Z.
Для всех X и Z ,
X — предок Z, если
(1) X — родитель Y и
существует Y , такой, что
(2) Y — предок Z.
Теперь отношение «предок» будет содержать два правила: одно для ближайших предков, другое для отдаленных.
Составим процедуру — множество утверждений об одном и том же отношении.
ancestor(X, Z):-
pearent(X, Z) .
ancestor(X, Z):-
pearent(X, Y),
ancestor(Y, Z).
Ключевым моментом в данной формулировке было использование отношения «предок» в его определении. Такое определение называется рекурсивным.
Упражнение 1.2.
В программу из упражнения 1.1 включите отношение ancestor. Задайте системе вопрос
Goal: ancestor(tom, pat)
и изобразите на диаграмме, какие шаги сделает система для достижения этой цели.
