Добавил:
natribu.org Все что нашел в интернете скидываю сюда Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Точно Не проект 2 / Не books / Источник_1

.pdf
Скачиваний:
10
Добавлен:
01.02.2024
Размер:
20.67 Mб
Скачать

300

Глава 5

 

 

;правило 9

((and (atom (car p))

(eq (car-letter (car p)) #\$)) (cond ((match (cdr p)(cdr d))

(set (cdr-name (car p)) (list (car d))) t)

((match p (cdr d)) (set (cdr-name (car p))

(cons (car d)(eval (cdr-name (car p)))))

t)))

Аналогично предыдущему правилу вначале убеждаемся, что очередной элемент образца – это атом, начинающийся с символа #\$. Затем, после проверки сопоставимости хвостовых частей списков Р и D или списка Р и хвостовой части списка D, выполняется функция SET. Данная функция присваивает переменной образца значение, соответствующее сегменту списка данных. Рассмотрим этот процесс на примере:

(match ’(?F $V) ’(Petrov 1975 5 October))

При попытке сопоставления параметра ?F с первым элементом списка данных функция МАТСН в соответствии с правилом 8 осуществит рекурсивный вызов

(match ’($V) ’(1975 5 October))

Данный вызов будет обрабатываться с помощью правила 9. Так как (CDR P) и (CDR D) не сопоставимы, то будет выполнен рекурсивный вызов (MATCH ’($V) ’(5 October)). Данный процесс повторится еще один раз. После вызова (МАТСН ’($V) ’(October)) функция МАТСН устанавливает, что хвостовые части списков Р и D сопоставимы (т.е. NIL:=:NIL). Это приводит к выполнению подстановки V←(October) c помощью вызова:

(set (cdr-name (car p)) (list (card)))

Затем управление передается в точку предыдущего вызова функции МАТСН, т.е. во вторую ветвь условного выражения COND правила 9. Это обеспечивает добавление в начало списка, доступ к которому осуществляется через переменную V, сначала числа 5, а затем числа 1975. Переменная V получает значение списка (1975 5 October). Указанное добавление элементов в список V реализует с помощью следующего вызова функции SET:

(set

(cdr-name (car p))

; выделить имя переменной

(cons

; добавить

(car d)

; первый элемент из d

(eval (cdr-name (car p))))); к значению переменной

Язык Лисп

301

 

 

Значение переменной можно использовать в процессе сопоставления. Например, можно потребовать, чтобы все встречающиеся в образце переменные с одинаковым именем сопоставлялись с одним и тем же значением. При этом возможны два случая. Если сопоставляемая переменная встретилась первый раз, то результат сопоставления просто запоминается. Если переменная встречалась ранее, то следует соответствующий параметр в образце заменить его значением и повторить процесс сопоставления. Обычно значения параметров хранят с помощью ассоциативного списка. Например, результаты предыдущего сопоставления параметров ?F и $V

можно хранить в виде a-списка((F . Petrov) (V . (1975 5 October))).

Формировать такой список можно с помощью функции ACONS. Для реализации возможности сопоставления повторяющейся переменной образца с одним и тем же значением, необходимо изменить соответствующим образом правила 8 и 9 функции МАТСН. Присвоение значений переменным должно выполняться только в том случае, если они отсутствуют в а-списке. Организовать соответствующий поиск переменных в а-списке можно с помощью функции ASSOC. Предоставим возможность расширения правил 8 и 9 читателю.

Функцию МАТСН можно совершенствовать дальше, используя ограничивающий параметр в образце, который дает возможность накладывать определенные ограничения на сопоставляемое значение. Обычно такие ограничения задаются с помощью предикатов. Будем представлять ограничения в виде подсписков образца [95]:

(restrict < ? | ?переменная > {< предикат >} )

Здесь предикат – функция с одним аргументом, который соответствует текущему сопоставляемому элементу списка данных. Если предикат (предикаты) принимает для текущего элемента данных истинное значение, то считается, что сопоставление успешно, и переменная получает соответствующее значение. Например,

(match ’((restrict ?V integerp evenp) b c) ’(36 b c)) T

(match ’((restrict ?V integerp evenp) b c)

’(36.0 b c)) NIL

В примере параметр ?V из подсписка ограничений сопоставляется с первым элементом списка данных. Если рассматриваемый элемент данных является целым четным числом, то сопоставление успешно.

Для обработки подсписков ограничений образца введем в функцию МАТСН два новых правила. Одно из правил будет применяться, когда в

302

Глава 5

 

 

подсписке ограничений используется параметр вида ?, а другое – параметр вида ?V:

; правило 10

((and (not(atom (car p))) (eq (caar p) ’restrict)

(eq (cadar p) ’?) (and-to-list

(mapcar #’(lambda (pred)

(funcall pred (car d))) (cddar p))))

(match (cdr p)(cdr d)))

; правило 11

((and (not (atom (car p)))

(not (atom d))

(eq (caar p) ’restrict)

(eq (car-letter (cadar p)) #\?) (and-to-list

(mapcar #’(lambda (pred)

(funcall pred (car d))) (cddar p))) (match (cdr p)(cdr d)))

(set (cdr-name (cadar p)) (car d)) t)

В соответствии с правилом 10, после проверки необходимых тестов, позволяющих установить, что очередной элемент образца – подсписок ограничений, к сопоставляемому элементу данных посредством отображающего функционала МАРСАR применяются последовательно предикаты, заданные в подсписке ограничений. Результаты применения предикатов возвращаются в виде списка, элементами которого являются логические значения. Функция AND-TO-LIST проверяет, все ли элементы списка имеют значение Т:

(defun and-to-list ( l )

;l - список логических значений

(setq res t) (dolist (temp l res)

(setq res (and res temp))))

Если отмеченное условие выполняется, то это означает, что параметр ? из подсписка ограничений успешно сопоставлен, и можно перейти к сопоставлению хвостовых частей списков Р и D.

Правило 11 выполняется сходным образом. Отличие заключается только в присвоении переменной значения с помощью вызова

(set (cdr-name (cadar p)) (car d))

Язык Лисп

303

 

 

Используя рассмотренную функцию сопоставления с образцом, можно написать простейшую программу, поддерживающую беседу на естественном языке. Такая программа основана на распознавании ответа пользователя с помощью функции МАТСН и формировании подходящего по смыслу вопроса.

Определим функцию, обеспечивающую общение на естественном языке, и назовем ее ELIZA в честь известной программы, разработанной Дж. Вейценбаумом. В приведенном варианте функция ELIZA обеспечивает ведение краткого диалога, касающегося погоды и отдыха. Оригинальная программа ELIZA имитировала общение с психотерапевтом [11].

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

(defun eliza()

(setq name nil) (setq otpusk nil)

(loop

(terpri)

(princ "Говорите >") (setq fact (read))

;правила

(cond ((equal fact ’( )) (return “До свидания”))

((match ’($ Добрый день $) fact)

(princ “Добрый день. Как вас зовут ?”) (setq name t))

(name (match ’(?n $) fact) (setq name nil)

(princ n)(princ “, О чём вы хотели поговорить ?”))

((match ’($ o чём $ говорить $) fact)

(princ “Конечно о погоде”) (terpri)

(princ “Какую погоду вы любите?”))

((match ’($ снег $) fact)

(princ “В такую погоду хорошо кататься на лыжах”) (terpri)

(princ “На чём вы любите кататься ?”))

((match '(На ?thing) fact)

304

Глава 5

 

 

(princ “Кататься на “)(princ thing)(princ “ – тоже не плохо”)

(terpri)

(princ “У вас будет отпуск зимой или летом?”))

((match ’($ летом $) fact)

(princ “А где вы отдыхали прошедшим летом?”))

((match ‘($ отдыхал $ (restrict ?place place_p) ) fact)

(princ “Куда вы планируете поехать в следующий отпуск?”) (setq otpusk t))

((match ’($ na ?p $) fact)

(princ p)(princ “Прекрасное место”)

(terpri)

(princ “Вы бывали там раньше?”))

(otpusk (princ “Вы говорили о”)

(princ place) (terpri)

(princ “Рассказать вам мою историю о”)

(princ place)(princ “?”)

(setq otpusk nil))

(t (princ “К сожалению, нам пора прощаться. Продолжим нашу беседу в следующий раз. Напечатайте ( ).”)))))

; предикат, проверяющий наличие сведений о месте отдыха

(defun place_p(x) (cond ((eq x ’Крыму) t)

((eq x ’Кавказе) t)

((eq x ’Киеве) t)))

Приведенная программа является тривиальной, однако, даже в таком простейшем варианте она способна на краткий диалог:

(eliza)

Говорите> (Добрый день)

ДОБРЫЙ ДЕНЬ. КАК ВАС ЗОВУТ?

Говорите> (Иван)

Иван, о чём вы хотели поговорить?

Говорите> (о чём можно говорить?)

КОНЕЧНО О ПОГОДЕ. КАКУЮ ПОГОДУ ВЫ ЛЮБИТЕ? Говорите> (Мне нравится, когда идет снег)

В ТАКУЮ ПОГОДУ ХОРОШО КАТАТЬСЯ НА ЛЫЖАХ. НА ЧЁМ ВЫ ЛЮБИТЕ КАТАТЬСЯ?

Говорите> (На санках)

КАТАТЬСЯ НА САНКАХ ТОЖЕ НЕПЛОХО. У ВАС БУДЕТ ОТПУСК ЗИМОЙ ИЛИ ЛЕТОМ?

Язык Лисп

305

 

 

Говорите> (Летом)

А ГДЕ ВЫ ОТДЫХАЛИ ПРОШЕДШИМ ЛЕТОМ? Говорите> (Я отдыхал на Кавказе)

КУДА ВЫ ПЛАНИРУЕТЕ ПОЕХАТЬ В СЛЕДУЮЩИЙ ОТПУСК?

Говорите> (На Сахалин) САХАЛИН ПРЕКРАСНОЕ МЕСТО.

ВЫ БЫВАЛИ ТАМ РАНЬШЕ? Говорите> (Несколько раз)

РАССКАЗАТЬ ВАМ МОЮ ИСТОРИЮ О КАВКАЗЕ

Говорите> (Да, пожалуйста)

К СОЖАЛЕНИЮ, НАМ ПОРА ПРОЩАТЬСЯ. ПРОДОЛЖИМ НАШУ

БЕСЕДУ В СЛЕДУЮЩИЙ РАЗ. НАПЕЧАТАЙТЕ ().

5.25.5. Поиск в семантических сетях

Рассмотрим семантическую сеть, изображенную на рисунке 5.14. Представим объекты и отношения семантической сети с помощью списка свойств. При этом объекты семантической сети будут представляться соответствующими символами языка ЛИСП, а отношения – свойствами символа:

(setf (get ’животное ’покров) ’кожа)

(setf (get ’птица ’покров) ’перья)

(setf (get ’птица ’передвижение) ’летать)

(setf (get ’рыба ’передвижение) ’плавает)

(setf (get ’страус ’передвижение) ’ходит) (setf (get ’пингвин ’передвижение) ’ходит) (setf (get ’пингвин ’цвет) ’черно-белый)

(setf (get ’канарейка ’цвет) ’желтый) (setf (get ’канарейка ’звук) ’пение) (setf (get ’малиновка ’цвет) ’красный)

(setf (get ’малиновка ’звук) ’пение)

Используя введенное представление семантической сети, определим функции, обеспечивающие поиск значений свойств в соответствии с иерархией объектов:

(setf (get ’малиновка ’аkо) ’птица)

(setf (get ’канарейка ’аkо) ’птица) (setf (get ’пингвин ’аkо) ’птица)

(setf (get ’страус ’аkо) ’птица) (setf (get ’птица ’аkо) ’животное)

(setf (get ’рыба ’аkо) ’животное)

(setf (get ’чилли-вилли ’is-a) ’пингвин) (setf (get ’матильда ’is-a) ’канарейка)

306

Глава 5

 

 

Рисунок 5.14 – Семантическая сеть части животного мира

Рассмотрим простейший вариант поиска в глубину. Определим функцию findproperty(p x n), возвращающую значения свойства p для заданного объекта x. Третий параметр функции – ограничивает глубину поиска:

(detun findproperty(p x n)

;p - свойство

;x - объект

;n - глубина поиска

(cond ((and (get x ’is-a) (eq p ’ako))

(format t “~s является экземпляром класса” x) (values))

((zerop n) nil) ; достигнута максимальная глубина ((get x p)) ; свойство найдено

(t (or (findproperty p (get x ’ako) (- n 1)) (findproperty p (get x ’is-a) (- n 1))

Здесь сначала выясняется, не является ли объект x экземпляром некоторого класса. С этой целью проверяется наличие свойства is-a. Если данное свойство обнаружено, то проверяется, не запрашивается ли при этом значение свойства ako. В случае обнаружения указанного совпадения функция возвращает сообщение: “x является экземпляром класса”. Такое сообщение формируется, например, при вызове

Язык Лисп

307

 

 

(findproperty ’ako ’чилли-вилли’ 5)

Второй тест, выполняемый в функции findproperty, обеспечивает проверку граничной глубины поиска.

Извлечение значения необходимого свойства объекта x выполняется с помощью теста (get x p ). Если данный вызов возвращает значение nil, то выполняется рекурсивный поиск свойства p с учетом иерархии ako или is-a связей. Для этого функция findproperty вызывается рекурсивно, и предпринимается попытка найти заданное свойство у объекта, который возвращается в результате вызова (get x ’ako) или (get x ’is-a). Эти вызовы возвращают имя соответствующего суперкласса или класса для рассматриваемого объекта. Таким образом, поиск выполняется по иерархии объектов в соответствии со структурой семантической сети.

Вопросы для самопроверки

1.Определите следующие основные понятия языка Лисп: атом, s-выражение, точечная пара, список.

2.Нарисуйте диаграмму точечной пары ((a . b) .((c . d) . (e . f)))

3.Что в языке Лисп называют формой, и какими конструкциями языка она представляется?

4.Сформулируйте правила интерпретации, используемые в Лиспе.

5.Приведите примеры вызовов основных арифметических функций языка Лисп.

6.Объясните на примерах назначение функций CAR, CDR, CONS.

7.Приведите примеры вызовов встроенных функций обработки списков.

8.Объясните на примерах особенности применения форм: SET,SETQ,SETF.

9.Какие функции в языке Лисп выполняют сравнение данных?

10.Перечислите предикаты языка Лисп, которые позволяют проверять типы значений.

11.Что называется лямбда-выражением и лямбда-вызовом?

12.Определите на языке Лисп функцию, возвращающую список, составленный из двух ее аргументов.

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

14.Объясните понятия лексической и специальной переменных языка Лисп.

15.Приведите пример вызова формы COND.

16.Какие средства можно использовать для организации итерационных циклических вычислений?

17.Определите функцию MEMBER, используя рекурсию.

18.Приведите примеры вызовов функций RPLACA, RPLACD, NCONC.

19.Что называют ассоциативным списком? Какие функции имеются в языке Лисп для работы с ассоциативными списками.

20.Что представляет собой символ языка Лисп?

21.Как выполнить ввод-вывод данных из файла? Приведите примеры.

22.Что в языке Лисп называют функционалом?

308

Глава 5

 

 

23.Объясните действия, выполняемые функционалами FUNCALL, APPLY, MAPCAR, MAPLIST.

24.Что называют обратной блокировкой?

25.Что называют замыканием?

26.Определите на языке Лисп структуру. Как создать экземпляр структуры? Как получить доступ к слотам структуры?

27.Приведите пример определения простого класса на языке Лисп и создайте экземпляр класса.

28.Объясните понятие “опции слота”, иcпользуемое при вызове макроформы

DEFCLASS.

29.Как определить метод класса?

30.Что в языке Лисп понимают под общей (родовой) функцией?

31.Объясните схему наследования свойств классов в языке Лисп?

32.Объясните отличие макроса от функции в языке Лисп.

33.Напишите на языке Лисп функцию, реализующую поиск в глубину в пространстве состояний.

34.Сформулируйте правила сопоставления с образцом, когда образец и данные представляются в виде линейных списков.

35.Напишите на языке Лисп функцию сопоставления с образцом для случая, когда образец и данные представляются в виде линейных списков.

36.Опишите на языке Лисп семантическую сеть, изображенную на рисунке 3.7.

ГЛАВА 6

ЯЗЫК ПРОЛОГ

Язык Пролог был разработан в начале семидесятых годов в университете Марселя (Франция) под руководством А. Колмероэ. Само название языка определяет его суть – язык логического программирования.

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

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

6.1. Общая характеристика языка

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

Соседние файлы в папке Не books