- •1.1 Пример программы: родственные отношения.
- •1.2 Факты.
- •1.3 Вопросы.
- •1.4 Переменные.
- •1.5 Конъюнкция целей.
- •1.6 Правила.
- •1.7 Конъюнкция в правилах.
- •2.1 Синтаксис пролога.
- •2.1.1 Константы.
- •2.1.2 Переменные.
- •1.8 Переменные в теле правила.
- •1.9 Cтруктура пролог-программы.
- •2.1.3 Структуры.
- •2.1.4 Операторы - тоже функторы.
- •2.2 Арифметика.
- •2.3 Операции сравнения.
- •2.4 Сопоставление.
- •2.6 Примеры сопоставления структур.
- •3.1 Декларативная семантика Пролог-программ
- •3.2 Дизъюнкция целей
- •3.3 Процедурная семантика
- •3.3.1 Пример вычисления
- •3.3.2 Формальное описание процедуры вычисления целей.
- •3.4 Соотношение между процедурным и декларативным смыслом
- •4.1 Списки
- •4.1.1 Представление списка диаграммой.
- •4.1.2 Выделение головы и хвоста списка
- •4.1.3 Шаблоны списков.
- •4.1.4 Определения отношений через cons форму списка
- •4.1.4 Определения отношений через cons форму списка
- •4.2 Процедуры обработки списков
- •4.2.3 Применение append
- •4.2.5 Длина списка
- •4.3 Встроенные предикаты
- •4.3.1 Простые встроенные предикаты ввода-вывода.
- •4.3.2 Процедурный смысл встроенных предикатов ввода-вывода.
- •4.4 Ввод-вывод списков.
- •4.4.1 Ввод-вывод списка как терма.
- •4.4.2 Поэлементный ввод-вывод списка.
- •5.1 Отсечение.
- •5.1.1 Графическая иллюстрация действия cut.
- •5.1.2 Пример действия cut.
- •5.1.3 Применение cut при выборе альтернатив.
- •5.1.4 Формальное описание действия отсечения.
- •5.2 Применение отсечения.
- •5.2.2 Добавление элемента без дублирования.
- •5.2.3 Классификация.
- •5.2.4 Отсечение в численной рекурсии.
- •5.2.5 Замечания при использовании отсечения.
- •5.3 Сортировка списков.
- •5.3.1 Метод наивной сортировки.
- •5.3.2 Метод пузырька.
- •5.3.3 Mетод вставки.
- •5.3.4 Быстрая сортировка quick.
- •6.1 Отрицание как неудача. (not as failure)
- •6.2 Алгоритм поиска на Прологе. ( Логический подход к задаче о фермере, волке, козе и капусте.)
- •6.3 Чтение и запись информации с файлов.
- •6.3.1 Обработка входных потоков.
- •6.3.2 Обработка выходных потоков.
- •6.4 Обработка символов.
- •7.1 Встроенные предикаты
- •7.1.2 Проверка типа терма
- •7.2 Метапредикаты.(Встроенные предикаты обработки термов.)
- •7.2.1 Создание и декомпозиция термов.
- •7.2.2 Предикаты работы с базой данных
- •7.3 Поиск в лабиринте
- •7.4 Сравнительная характеристика языков программирования.
- •8.1. Операции (Операторы).
- •8.1.1 Приоритет оператора.
- •8.1.2. Тип оператора.
- •8.1.3 Объявление операций.
- •8.2. Поиск.
- •8.2. Поиск.
- •8.2.1 Поиск в Прологе.
- •8.2.2 Поиск в глубину.
- •8.2.3 Поиск в ширину.
- •8.2.4 Резюме Поиска.
- •9.1. Введение
- •9.2 Поиск с предпрочтением.
- •10.1. Постановка задачи
- •10.2. Пример грамматики
- •10.3. Пример разбора вручную.
- •10.4. Реализация грамматического разбора на Прологе.
- •Как должны выглядеть утверждения Пролога ?
- •Запоминание состояния в Прологе.
- •Аналогично для dcg проводится
- •11.1. Постановка задачи
- •Две емкости
- •11.2. Решение задачи
- •12.1. Постановка задачи
- •12.2. Решение
- •13.1. Введение
- •Метод "образовать и проверить"
- •13.2. Раскрашивание плоской карты
4.1.2 Выделение головы и хвоста списка
|
|
|
Главной операцией при работе со списками является расщепление списка на голову и хвост. |
|
|
В Лиспе для этого используются функции car и cdr.
В Прологе имеется специальная форма представления списка, называемая cons-формой записи:
[Head|Tail] или [H|T] [a|[]] = [а]
При конкретизации формы списком H сопоставляется с головой списка, а Т - с хвостом.
Например
|
р([a,b,c]). |
|
?-p([X|Y]). yes X=a Y=[b,c] |
|
|
|
|
Таким образом выделяются одновременно голова списка и хвост.
Рассмотрим сопоставление двух списков :
|
|
4.1.3 Шаблоны списков.
Шаблон (образец) списка -это форма описания множества (семейства)списков, обладающих определенными свойствами.
Например:
Шаблон списка [X|Y] описывает любой список,состоящий не менее чем из одного элемента.
Шаблон [X,Y|Z] - список, состоящий не менее чем из двух элементов.
Шаблон [b|Z] - список, первым элементом которого является b.
Шаблон [Y,X,Z] - список из трех элементов.
Шаблоны списка используются при описании процедур работы со списками.
4.1.4 Определения отношений через cons форму списка
Задача 1: Определить отношение replace_first, которое заменяет первый элемент списка новым
Например
|
?-replace_first([a,b,с],w,X). X=[w,b,c] |
|
|
|
|
Это отношение:
|
replace_first([H|T],A,[A|T]). или replace_first([_|T],A,[A|T]). |
Что будет ответом для следующего вопроса ?
|
?-replace_first([_|T],A,[a,b,c]). |
4.1.4 Определения отношений через cons форму списка
Задача 1: Определить отношение replace_first, которое заменяет первый элемент списка новым
Например
|
?-replace_first([a,b,с],w,X). X=[w,b,c] |
|
|
|
|
Это отношение:
|
replace_first([H|T],A,[A|T]). или replace_first([_|T],A,[A|T]). |
Что будет ответом для следующего вопроса ?
|
?-replace_first([_|T],A,[a,b,c]). |
4.2 Процедуры обработки списков
Процедура в прологе - это совокупность предложений с головами, представленными одинаковыми термами.
Для обработки списков используются типовые процедуры, аналогичные функциям лиспа.
member - проверяет принадлежность элемента списку
append - используется для соединения двух списков
reverse - обращает список
length - вычисляет длину списка
remove - удаляет элемент из списка
4.2.1 member
Проверяет принадлежность элемента списку.
|
member(X, L) |
Если X принадлежит L, то истина и ложь в противном случае.
С точки зрения декларативного смысла:
X принадлежит списку, если X совпадает с головой списка.
X принадлежит списку, если X принадлежит хвосту списка.
Можно записать:
|
member(X, [X|T]). member(X, [H|T]) :-member(X, T). |
С точки зрения процедурного смысла - это рекурсивная процедура.
Первое предложение терминальное условие. Когда хвост будет равен [] проверка остановиться.
Второе предложение рекурсивное. Сокращение списка происходит за счет взятия хвоста (cdr-рекурсия).
Примеры применения
|
?-member(a, [a, b, с]). Yes ?-member(X, [a, b, с]). Yes X = a X = b X = c |
|
|
|
|
Ответьте на вопрос:
|
?-member(a, X). |
|
|
|
|
4.2.2 append
Используется для соединения двух списков. т.е
|
append (L1, L2, L3) |
L1 и L2 - списки, а L3 - их соединение.
|
?-append ([a, b], [c], [a,b,c]). Yes |
|
|
|
|
Для определения процедуры append используем два предложения:
Если присоединить пустой список [] к списку L, то получим список L.
append([], L, L). append([X|L1], L2, [X|L3]):- append(L1, L2, L3).
Если присоединить не пустой список [X|L1] к списку L2, то результатом будет список [X|L3], где L3 получаeтся соединением L1 к L2 :
-
|X| L1 | L2 |
----------------------------------------
|X| L3 |
С точки зрения процедурной семантики первое предложение - терминальное условие, второе - рекурсивное с хвостовой рекурсией.
Рассмотрим примеры применения
|
?-append([a], [b, c], L). L=[a, b, c] ?-append([a], L, [a, b, c]). L=[b, c] ?-append(L, [b, c], [a, b, c]). L=[a] |
|
|
|
|
Можно использовать для разбиения
|
?-append(L1, L2, [a, b, c]). L1=[] L2=[a, b, c]; L1=[a] L2=[b, c]; L1=[a, b] L2=[c]; L1=[a, b, c] L2=[] |
