Чтение онлайн

ЖАНРЫ

Программирование на языке Пролог для искусственного интеллекта

Братко Иван

Шрифт:

если

Условие
то
Цель1
иначе
Цель2

С использованием отсечения эта конструкция переводится на Пролог так:

Условие, !. % Условие выполнено?

Цель1; % Если да, то Цель1

Цель2 % Иначе - Цель2

• Из-за того, что оператор

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

• Внесение изменений в программу при помощи

assert
и
retract
может сделать поведение программы значительно менее понятным. В частности, одна и та же программа на одни и те же вопросы будет отвечать по-разному в разные моменты времени. В таких случаях, если мы захотим повторно воспроизвести исходное поведение программы, нам придется предварительно убедиться в том, что ее исходное состояние, нарушенное при обращении к
assert
и
retract
, полностью восстановлено.

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

Для иллюстрации некоторых положений данного раздела рассмотрим отношение

слить( Спис1, Спис2, Спис3)

где

Спис1
и
Спис2
 — упорядоченные списки, а
Спис3
 — результат их слияния (тоже упорядоченный). Например:

слить( [2, 4, 7], [1, 3, 4, 8], [1, 2, 3, 4, 4, 7, 8] )

Вот стилистически неудачная реализация этого отношения:

слить( Спис1, Спис2, Спис3) :-

 Спис1 = [], !, Спис3 = Спис2;

% Первый список пуст

 Спис2 = [], !, Спис3 = Спис1;

% Второй список пуст

 Спис1 = [X | Остальные],

 Спис2 = [Y | Остальные],

 ( X < Y, !,

Z = X, % Z - голова Спис3

 слить( Остальные1, Спис2, Остальные3 );

 Z = Y,

 слить( Спис1, Остальные2, Остальные3 ) ),

 Спис3 = [Z | Остальные3].

Вот более предпочтительный вариант, не использующий точек с запятой:

слить( [], Спис, Спис).

слить( Спис, [], Спис).

слить( [X | Остальные1], [Y | Остальные2], [X | Остальные3] ) :-

 X < Y, !,

 слить(Остальные1, [Y | Остальные2], Остальные3).

слить( Спис1, [Y | Остальные2], [Y | Остальные3]): -

 слить( Спис1, Остальные2, Остальные3 ).

8.3.2. Табличная организация длинных процедур

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

Преимущества такой организации длинной процедуры состоят в том, что:

• Ее структуру легко понять.

• Ее удобно совершенствовать: улучшать ее можно, просто добавляя новые факты.

• Ее легко проверять и модифицировать (просто заменяя отдельные факты, независимо от остальных). 

8.3.3. Комментирование

Программные комментарии должны объяснять в первую очередь, для чего программа предназначена и как ею пользоваться, и только затем — подробности используемого метода решения и другие программные детали. Главная цель комментариев — обеспечить пользователю возможность применять программу, понимать ее и, может быть, модифицировать. Комментарии должны содержать в наиболее краткой форме всю необходимую для этого информацию. Недостаточное комментирование — распространенная ошибка, однако, программу можно и перенасытить комментариями. Объяснения деталей, которые и так ясны из самого текста программы, являются ненужной перегрузкой.

Длинные фрагменты комментариев следует располагать перед текстом, к которому они относятся, в то время как короткие комментарии должны быть вкраплены в сам текст. Информация, которую в самом общем случае следует включать в комментарии, должна схватывать следующие вопросы:

• Что программа делает, как ею пользоваться (например, какую цель следует активизировать и каков вид ожидаемых результатов), примеры ее применения.

• Какие предикаты относятся к верхнему уровню?

• Как представлены основные понятия (объекты)?

• Время выполнения и требования по объему памяти.

• Каковы ограничения на программу?

• Использует ли она какие-либо средства, связанные с конкретной операционной системой?

• Каков смысл предикатов программы? Каковы их аргументы? Какие аргументы являются "входными" и какие — "выходными", если это известно? (В момент запуска предиката входные аргументы имеют полностью определенные значения, не содержащие не конкретизированных переменных.)

• Алгоритмические и реализационные детали.

8.4. Отладка

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

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

Основным средством отладки является трассировка (tracing). "Трассировать цель" означает: предоставить пользователю информацию, относящуюся к достижению этой цели в процессе ее обработки пролог-системой. Эта информация включает:

• Входную информацию — имя предиката и значении аргументов в момент активизации цели.

• Выходную информацию — в случае успеха, значения аргументов, удовлетворяющих цели; в противном случае — сообщение о неуспехе.

• Информацию о повторном входе, т.е. об активизации той же цели в результате автоматического возврата.

Поделиться с друзьями: