Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
IIS / Лекции / ЛР 2 5 - Prolog задание 4.doc
Скачиваний:
38
Добавлен:
31.03.2015
Размер:
88.58 Кб
Скачать

Лабораторная работа № 7 Программирование интеллектуальных систем на языке Пролог Управление ходом выполнения программ в системе Турбо-Пролог (2 часть)

  1. Организация повторяющихся процессов

При выполнении запросов программа последовательно обращается к фактам и правилам. При этом правила часто требуют, чтобы задачи типа поиска элементов в базе, ввода или вывода данных выполнялись многократно. Однако в Прологе отсутствует возможность непосредственного задания итерационного процесса, т.е. не реализованы синтаксические конструкции типа FOR, WHILE или REPEAT.

Существует два способа построения правил, выполняющих одну и ту же задачу несколько раз. Это повторение, использующее возврат, и рекурсия, использующая вызов процедуры самой себя.

Повторение реализуется с использованием метода отката после неудачи, когда осуществляется возврат к последней, имеющей альтернативное решение, подцели, реализация альтернативы и очередной возврат. Поэтому поиск с возвратом можно использовать для выполнения повторяющихся процессов. Примером построения правила, использующего повторение, является предикат do_answer() в программе 8.

Но если этот подход применить к предикату query той же программы, т.е. искусственно вызвать состояние неудачи, добавив предикат fail в виде последней подцели правила, то никакого повторного запроса на ввод мы не получим.

Задание 1.

Вызовите программу 8, добавьте fail в конец описания query и, запустив программу на выполнение, убедитесь что процесс не повторяется. Объясняется это тем, что предикаты формирования окна и ввода не являются альтернативами, т.е. не имеют альтернативных решений, а предикат do_answer() все альтернативные решения получил, т.е. цель query является истинной и решение задачи заканчивается.

Для того, что обеспечить многократный ввод данных, необходимо, чтобы откат выполнялся к некоторому предикату, имеющему альтернативное решение, с одной стороны, и чтобы это решение было бы постоянно истинным, с другой стороны. При невыполнении последнего условия откат может произойти к еще более ранним подцелям и не обеспечит повторения именно нужной нам группы действий.

Используя простейшую рекурсию, процедура задания предиката для правила повтора, определяемого пользователем, может иметь вид:

repeat. repeat :- repeat.

Первая строка - это факт, который всегда успешен и объявляет предикат repeat истинным. Однако, так как есть для этого предиката еще одно правило, то указатель отката устанавливается на первый repeat. Вторая строка - это правило, которое использует самовызов. Правило (второй repeat) вызывает подцель (третий repeat), и этот вызов вычисляется успешно, так как факт (первый repeat) удовлетворяет подцели. Следовательно, правило также всегда успешно. Предикат repeat будет успешно вычисляться при каждой новой попытке его вызвать после отката. Таким образом, repeat - это рекурсивное правило, которое никогда не бывает неуспешным.

Задание 2.

Введите в программу описание предиката repeat. Вставьте обращение к этому предикату в качестве первой подцели правила query. Запустите на выполнение программу. Теперь у Вас появилась возможность повторного ввода, но нет признака окончания и единственный вариант выхода из программы - это Ctrl+Break.

Но для того, чтобы сформировать признак окончания повторений, давайте разберемся, как работает программа, и кто инициирует повтор. Первым выполняется repeat, который ничего не делает, далее - не имеющие альтернатив стандартные предикаты и последним предикат do_answer, который и обеспечивает откат после неудачи к предикату repeal за счет присутствия в нем предиката fail.

Задание 3.

Закомментируйте в правиле do_answer предикат fail и запустите программу на выполнение. Обратите внимание, что наличие в программе предиката repeat еще не обеспечивает повторов, что для организации повторов необходим возврат к предикату repeat. Снимите комментарий.

Но если откат к repeat вызывает do_answer, то он должен и обеспечить, при определенных условиях, окончание этого процесса. Если за условие выхода будет принят, например, ввод слова stop вместо фамилии, то можно доопределить предикат do_answer еще одним правилом:

do_answer(X) :- X="stop", write("good bye").

которое будет истинным при согласовании, и которое, ввиду отсутствия признака неудачи, не вызовет отката к предикату repeat.

Задание 4.

Добавьте новое правило в последнюю строку процедуры. Запустите программу на выполнение сначала в обычном режиме, а затем - в режиме трассировки, но только предиката do_answer. Переставьте новое правило на первую строку процедуры и выполните трассировку. Какой получился результат? Что будет, если правило для условия выхода записать в виде:

do_answer("stop"):-write("good bye").? Какой из этого следует вывод?

Обобщая изложенное, можно сделать вывод о том, что условие выхода из цикла может определяться любым предикатом, одно из множества альтернативных описаний которого должно содержать предикат fail или вызывать поиск с возвратом, т.е. обеспечивать откат.

Из анализа даже простейших случаев организации повторяющихся процессов, как реализуемых самой Пролог-системой, так и определяемых пользователем, можно сделать вывод о необходимости управления этими процессами со стороны пользователя.