Иван Братко - Программирование на языке Пролог для искусственного интеллекта
- Название:Программирование на языке Пролог для искусственного интеллекта
- Автор:
- Жанр:
- Издательство:Мир
- Год:1990
- Город:Москва
- ISBN:5-03-001425-Х
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Иван Братко - Программирование на языке Пролог для искусственного интеллекта краткое содержание
Книга известного специалиста по программированию (Югославия), содержащая основы языка Пролог и его приложения для решения задач искусственного интеллекта. Изложение отличается методическими достоинствами — книга написана в хорошем стиле, живым языком. Книга дополняет имеющуюся на русском языке литературу по языку Пролог.
Для программистов разной квалификации, специалистов по искусственному интеллекту, для всех изучающих программирование.
Программирование на языке Пролог для искусственного интеллекта - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Иногда нам может понадобиться более строгий вид равенства - буквальное равенство двух термов. Этот вид реализован еще одним встроенным предикатом, записываемым как инфиксный оператор ' ==
':
Т1 == Т2
Это равенство выполняется, если термы Т1 и Т2 идентичны, т.е. имеют в точности одинаковую структуру, причем все соответствующие компоненты совпадают. В частности, должны совпадать и имена переменных. Отношение "не идентичны", дополнительное к данному, записывается так:
T1 \== T2
Приведем несколько примеров:
?- f( a, b) == f( а, b).
yes
?- f( a, b) == f( a, X).
nо
?- f( a, X) == f( a, Y).
no
?- X \== Y.
yes
?- t( X, f( a, Y) ) == t( X, f( a, Y) ).
yes
Давайте в качестве примера переопределим отношение
счетчик( Терм, Список, N)
из разд. 7.1. Пусть на этот раз N будет числом буквальных вхождений Терм
'а в Список
:
счетчик( _, [], 0).
счетчик( Терм, [Голова | L], N) :-
Терм == Голова, !,
счетчик( Терм, L, N1),
N is N1 + 1;
счетчик( Терм, L, N).
7.4. Работа с базой данных
Реляционная модель предполагает, что база данных — это описание некоторого множества отношений. Пролог-программу можно рассматривать как именно такую базу данных: описание отношений частично присутствует в ней в явном виде (факты), а частично — в неявном (правила). Более того, встроенные предикаты дают возможность корректировать эту базу данных в процессе выполнения программ. Это делается добавлением к программе (в процессе вычисления) новых предложений или же вычеркиванием из нее уже существующих. Предикаты, используемые для этой цели, таковы: assert
(добавить), asserta
, assertz
и retract
(удалить).
Цель
assert( С)
всегда успешна, а в качестве своего побочного эффекта вызывает "констатацию" предложения С, т.е. добавление его к базе данных.
Цель
retract( С)
приводит к противоположному эффекту: удаляет предложение, сопоставимое с С. Следующий диалог иллюстрирует их работу:
?- кризис.
no
?- assert( кризис).
yes
?- кризис.
yes
?- retract( кризис).
yes
?- кризис.
no
Предложения, добавленные к программе таким способом, ведут себя точно так же, как и те, что были в "оригинале" программы. Следующий пример показывает, как с помощью assert
и retract
можно работать в условиях изменяющейся обстановки. Предположим, что у нас есть такая программа о погоде:
хорошая :-
солнечно, not дождь.
необычная :-
солнечно, дождь.
отвратительная :-
дождь, туман.
дождь.
туман.
Ниже приводится пример диалога с этой программой, во время которого база данных постепенно изменяется:
?- хорошая.
no
?- отвратительная.
yes
?- retract( туман).
yes
?- отвратительная.
no
?- assert( солнечно).
yes
?- необычная.
yes
?- retract( дождь).
yes
?- хорошая.
yes
Добавлять и удалять можно предложения любой формы. Следующий пример показывает, что, кроме того, retract
может работать недетерминировано: используя механизм возвратов с помощью только одной цели retract
можно удалить целое множество предложений. Предположим, что в программе, с которой мы "консультируемся", есть такие факты:
быстр( энн).
медл( том).
медл( пат).
К этой программе можно добавить правило:
?- assert(
( быстрее( X, Y) :-
быстр( X), медл( Y) ) ).
yes
?- быстрее( А, В).
А = энн
В = том
?- retract( медл( X) ).
X = том;
X = пат;
nо
?- быстрее( энн, _ ).
nо
Заметьте, что при добавлении нового правила синтаксис требует, чтобы оно (как аргумент assert
) было заключено в скобки.
При добавлении нового предложения может возникнуть желание указать, на какое место в базе данных его следует поместить. Такую возможность обеспечивают предикаты asserta
и assertz
. Цель
asserta( С)
помещает С в начале базы данных. Цель
assertz( С)
— в конце. Вот пример, иллюстрирующий работу этих предикатов:
?- assеrt( p( a)), assertz( p( b) ), asserta( p( c) ).
yes
?- p( X).
X = с;
X = а;
X = b
Между consult
и assertz
существует связь. Обращение к файлу при помощи consult
можно в терминах assertz
определить так: считать все термы (предложения) файла и добавить их в конец базы данных.
Одним из полезных применений предиката asserta
является накопление уже вычисленных ответов на вопросы. Пусть, например, в программе определен предикат
решить( Задача, Решение)
Мы можем теперь задать вопрос и потребовать, чтобы ответ на него был запомнен, с тем чтобы облегчить получение ответов на будущие вопросы:
?- решить( задача1, решение),
asserta( решить( Задача1, Решение) ).
Если в первой из приведенных целей будет успех, ответ ( Решение)
будет сохранен, а затем использован так же, как и любое другое предложение, при ответе на дальнейшие вопросы.
Преимущество такого "запоминания" состоит в том, что на дальнейшие вопросы, сопоставимые с добавленным фактом, ответ будет получен, как правило, значительно быстрее, чем в первый раз. Ответ будет теперь получен как факт, а не как результат вычислений, требующих, возможно, длительного времени.
Развитие этой идеи состоит в использовании assert
для порождения всех решений в виде таблицы фактов. Например, создать таблицу произведений всех чисел от 0 до 9 можно так: породить пару чисел X и Y, вычислить Z, равное X * Y, добавить эти три числа в виде строки в таблицу произведений, а затем создать искусственно неуспех. Неуспех вызовет возврат, в результате которого будет найдена новая пара чисел, и в таблицу добавится новая строка и т.д. Эта идея реализована в процедуре
таблица :-
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
принадлежит( X, L), % Выбрать первый сомножитель
принадлежит( Y, L), % Выбрать второй сомножитель
Z is X*Y,
assert( произв( X,Y,Z) ),
fail.
Вопрос
?- таблица.
потерпит, конечно, неудачу, однако в качестве своего побочного эффекта приведет к добавлению в базу данных целой таблицы произведений. После этого можно, например, спросить, какие пары дают произведения, равные 8:
?- произв( А, В, 8).
А = 1
В = 8;
А = 2
В = 4;
...
Здесь следует сделать одно замечание, относящееся к стилю программирования. Приведенные примеры показали некоторые явно полезные применения assert
и retract
. Однако использование этих отношений требует особой внимательности. Не рекомендуется применять их слишком часто и без должной осторожности - это плохой стиль программирования. Ведь добавляя и удаляя предложения, мы фактически изменяем программу. Поэтому отношения, выполнявшиеся в некоторой ее точке, могут оказаться неверными в другой. В разные моменты времени ответы на одни и те же вопросы будут различными. Таким образом, большое количество обращений к assert
и retract
может затемнить смысл программы и станет трудно разобрать, что истинно, а что — нет. В результате поведение программы может стать непонятным, трудно объяснимым, и вряд ли можно будет ей доверять.
Интервал:
Закладка: