- •Введение
- •1.Основные элементы языка Пролог. Структура программы на языке Пролог.
- •2. Структуры. Состав логических операций в Прологе. Решение логической задачи в tp.
- •3. Использование рекурсии. Построение программ с использованием основных структур данных Пролога - списков.
- •1.Принадлежность.
- •2.Сцепление.
- •4. Использование механизма отсечения для оптимизации поиска решения в программах на Прологе.
- •5. Управление стратегией вывода в экспертных системах с помощью обратной цепочки рассуждений.
- •6. Управление стратегией вывода в экспертных системах с помощью прямой цепочки рассуждений.
- •7.Управление стратегией выбора в экспертных системах с помощью эвристик.
- •8. Получение вывода экспертными системами в условиях неопределённости.
- •9. Организация в экспертных системах ответов на вопросы “Почему” и “Как”.
- •Рекомендуемая литература.
3. Использование рекурсии. Построение программ с использованием основных структур данных Пролога - списков.
Рекурсия.
Рекурсивное определение предиката - это определение предиката через него самого. Рассмотрим следующий пример вычисления факториала:
domains
N,F=real
predicates
factorial(N,F) /*вычисляет N!, результат заносит в F*/
clauses
factorial(1,1)
factorial(N,R): - N>0,N1=N-1,
factorial(N1,R1),R=R1*N.
goal
factorial(N,F).
Схема работы программы:
Предположим, что пользователь выбрал цель: factorial(5,F). Протокол работы программы выглядит следующим образом. Выпишем последовательно все цели, которые должны быть доказаны.
Цель1:
factorial(5,R), если 5>0, N1=5-1,factorial(4,R1),R=R1*5.
То есть, предикат factorial (5,R) является истинным, если истины предикаты:
5>0 - (является истинным),
N1=5-1 - (является истинным при N1=4),
factorial(4,R1) (надо доказать),
R=R1*5 (надо даказать).
Цель 2:
factorial(4,R1), если 4>0,N11=4-1,factorial(3,R11),R1=R11*4.
Цель 3:
factorial(3,R11),если 3>0,N111=3-1,factorial(2,R111),R11=R111*3.
Цель 4:
factorial(2,R111), если 2>0,N1111=2- 1,factorial(1,R111),R111=R1111*2.
Цель 5:
factorial(1,R1111), если R1111=1
Возврат к цели 4:
factorial(2,R111) истинно при R111=2.
Возврат к цели 3:
factorial(3,R11) истинно при R11=6.
Возврат к цели 2:
factorial(4,R1) истинно при R1=24.
Возврат к цели 1:
factorial(5,R) истинно при R=120.
Ответ: F=120.
С помощью механизма рекурсивных типов данных можно весьма точно передать смысл фактов в программе. Рекурсия может быть использована для описания объектов, в которых количество элементов заранее неизвестно. Рассмотрим следующий пример:
Описать фамилии учащихся класса, в котором количество учеников заранее не известно.
Domains
сlass_list = nul; /*класс, в котором нет ни одного ученика*/
class(name,class_list) /*класс, в котором имеется class_list учеников и еще один, чья фамилия name */
name=symbol
Тогда факты будут описаны следующим образом:
сlass("Петров",class("Иванов",nul)) (2 ученика);
сlass("Петров",class("Иванов",class("Сидоров",nul))) (3 ученика).
Относительный порядок правил и фактов очень критичен при употреблении рекурсии. Обычно факты должны располагаться перед правилами и правила должны быть упорядочены от наиболее специфичных до наиболее общих. Если этого не сделать, то программа может войти в бесконечный цикл. Например, описанная ниже программа войдёт в бесконечный цикл:
peopl(X): - peopl(Y),mother(Y,X).
peopl("Адам").
Чтобы был найден факт об Адаме, необходимо использовать механизм возврата. Но для этого необходимо, чтобы Пролог потерпел неудачу при проверке первого утверждения. А это событие не произойдёт при данном описании. Если факт поставить перед правилом, то программа будет работать правильно.
Списки.
Список - это упорядоченная последовательность элементов, которая может иметь произвольную длину. Элементами списка могут быть: константы, переменные, структуры. Списки являются основной структурой данных на Прологе.
Синтаксически список определяется в виде последовательности элементов списка, разделенных запятыми и заключенных в квадратные скобки. Например, [1,2,3,4,3,2]. Такой список определяется пользователем следующим образом:
domains
list=integer*
Если элементы списка имеют смешанный тип (знаковые и целые), то должно быть соответствующее объявление:
domains
element=c(char); i(integer)
list=element*
Для удобства обработки списков в Прологе введены два понятия: Head(голова) и Tail(хвост). Работа со списками основана на расщеплении их на голову и хвост.
Операции над списками.