
- •2. Алгоритмы унификации
- •3. Структура пролог-программы
- •Раздел описания доменов (типов).
- •Раздел описания предикатов внутренней базы данных
- •Раздел описания предикатов
- •Раздел описания предложений
- •Раздел описания внутренней цели
- •4. Организация повторов
- •8. Сортировка списков
- •9. Выборка элементов из списков
- •10. Слияние списков
- •11. Множества в прологе
- •12. Реализация деревьев в прологе
- •13. Функциональный подход программирования.
- •14. Методы обработки списков (лисп).
- •15. Определение универсальной функции.
- •16. Предикаты и истинность в лиспе.
- •17. Отображения и функционалы
- •Отображения структур данных и функционалы
- •18. Имена, определения и контексты в лисп
- •19. Prog выражения и циклы в лисп Свойства атомов и категории функций
- •Prog-выражения и циклы
- •20. Списки свойств атомов и структура списков
- •Представление структуры списка
- •21. Числа и мультиоперации
- •22. Функционалы - общее понятие.
- •23. Безымянные функции
- •24. Экспертные системы. Реализация в пролог и лисп
Раздел описания предложений
Этот раздел можно считать основным разделом программы, потому что именно в нем содержатся факты и правила, реализующие пользовательские предикаты. Все предикаты, которые применяются в этом разделе и не являются стандартными предикатами, должны быть описаны в разделе описания предикатов или в разделе описания предикатов базы данных.
Предложения, у которых в заголовке указан один и тот же предикат, должны идти друг за другом. Такой набор предложений называется ПРОЦЕДУРОЙ.
Раздел описания внутренней цели
Если этот раздел отсутствует, то после запуска программы Пролог-система выдает приглашение вводить вопросы в диалоговом режиме (внешняя цель). При выполнении внешней цели Пролог-система ищет все решения, выводя все возможные значения для переменных, участвующих в вопросе. Если же выполняется внутренняя цель, то осуществляется поиск только первого решения, а для получения всех решений нужно предпринимать дополнительные действия.
Программа, компилируемая в исполняемый файл, который можно запускать независимо от среды разработки, обязательно должна иметь внутреннюю цель. Внешнюю цель обычно применяют на этапе отладки программы.
.
.
4. Организация повторов
В Прологе для этого используются процедура поиска с возвратом (откат) и рекурсия. Откат дает возможность получить много решений в одном запросе к программе, а рекурсия позволяет использовать в процессе определения предиката его самого.
БАЗИС РЕКУРСИИ - это предложение, определяющее некую начальную ситуацию или ситуацию в момент прекращения. Как правило, в этом предложении записывается некий простейший случай, при котором ответ получается сразу даже без использования рекурсии.
ШАГ РЕКУРСИИ - это правило, в теле которого обязательно содержится, в качестве подцели, вызов определяемого предиката. Если мы хотим избежать зацикливания, определяемый предикат должен вызываться не от тех же параметров, которые указаны в заголовке правила. Параметры должны изменяться на каждом шаге так, чтобы в итоге либо сработал базис рекурсии, либо условие выхода из рекурсии, размещенное в самом правиле.
Рекурсивные алгоритмы, как правило, намного проще с логической точки зрения, чем итерационные. Некоторые алгоритмы удобно записывать именно рекурсивно.
НЕДОСТАТОК: может не хватать для работы стека. При каждом рекурсивном вызове предиката в специальном стековом фрейме запоминаются все промежуточные переменные, которые могут понадобиться. Максимальный размер стека при работе под управлением операционной системы MS DOS всего 64 Кб. Этого достаточно для размещения около трех-четырех тысяч стековых фреймов (в зависимости от количества и размера промежуточных переменных). При больших входных значениях стека может не хватить.
Есть, правда, один вариант рекурсии, который использует практически столько же оперативной памяти, сколько итерация в императивных языках программирования. Это так называемая хвостовая или правая рекурсия. Для ее осуществления рекурсивный вызов определяемого предиката должен быть последней подцелью в теле рекурсивного правила и к моменту рекурсивного вызова не должно остаться точек возврата (непроверенных альтернатив). То есть у подцелей, расположенных левее рекурсивного вызова определяемого предиката, не должно оставаться каких-то непроверенных вариантов и у процедуры не должно быть предложений, расположенных ниже рекурсивного правила.
5. Ветвление-выбор
6. Стандартные математические предикаты
.
.
7. СПИСКИ И ОПЕРАЦИИ НАД НИМИ (list = integer*)
Рекурсивное определение списка.
Список — это структура данных, определяемая следующим образом:
1. пустой список ([ ]) является списком;
2. структура вида [H|T] является списком, если H — первый элемент списка (или несколько первых элементов списка, перечисленных через запятую), а T — список, состоящий из оставшихся элементов исходного списка.
В императивных языках основной структурой данных являются массивы. В Прологе так же, как и в Лиспе, основным составным типом данных является список.
[] — пустой список, т.е. список, не содержащий элементов (в Лисп - nil).
Элементы списка могут быть любыми, в том числе и списками.
В классическом Прологе элементы списка могут принадлежать разным доменам, В Турбо Прологе, в связи со строгой типизацией, все элементы списка должны принадлежать одному домену. Однако можно разместить в одном списке объекты разной природы, используя домен с соответствующими альтернативами.
Операция "|" позволяет разделить список на хвост и голову (в Лиспе - car и cdr) или приписать объект (объекты) к началу списка (cons в Лиспе). Данное определение позволяет организовывать рекурсивную обработку списков, разделяя непустой список на голову и хвост.
Чтобы организовать обработку списка достаточно задать базис рекурсии (правило или факт, определяющее, что нужно делать с пустым списком), а также рекурсивное правило, устанавливающее порядок перехода от обработки всего непустого списка к обработке его хвоста.