Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Metodich.doc
Скачиваний:
5
Добавлен:
06.12.2018
Размер:
348.16 Кб
Скачать

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(хвост). Работа со списками основана на расщеплении их на голову и хвост.

Операции над списками.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]