Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Solomon.doc
Скачиваний:
17
Добавлен:
08.05.2019
Размер:
3.38 Mб
Скачать

Глава 11. Общение с компьютером на естественном языке

11.1. Введение

Настоящая глава посвящена проблеме возможности общения

с компьютером на естественном для человека языке, этой одной

из наиболее сложных областей искусственного интеллекта. Гла-

ва начинается с некого определения того, что скрывается за

понятием общения на естественном языке, и краткого обзора

достижений в этой области за последние годы.

Будут кратко рассмотрены несколько методов разбора

сформулированных на естественном языке предложений. Более

подробно будут освещены два из них: анализ ключевых слов и

контекстно-свободные грамматики (КС -грамматики), приведены

программы, использующие эти походы. Анализ ключевых слов

применим в естественно-языковых интерфейсах к базам данных и

экспертным системам. КС-грамматики являются следующим шагом

в реализиции общения на естественном языке. Встроенные пре-

дикаты Турбо-Пролога представляют из себя мощное средство

анализа естественно-языковых структур.

11.2. Различные подходы к проблеме общения на естественном

языке

Говоря о естественном языке, можно иметь в виду любой

язык, при помощи которого люди общаются между собой: англий-

ский, французский, японский, русский. Все эти языки имеют

структуры и правила, в соответствии с которыми люди констру-

ируют из слов фразы, фрагменты предложения, целые предложе-

ния. Когда говорят, что некто "общается на естественном язы-

ке" , то при этом имеют в виду не только понимание предложе-

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

самостоятельно.

Наука об общении с ЭВМ на естественном языке так же

стара, как и сама проблема искусственного интеллекта. Лисп,

первый язык искусственного интеллекта, был создан для целей

обработки символов, слов, списков, а также более сложных

списочных структур. Лисп достаточно часто используется в

разработках по проблеме общения на естественном языке. Язык

Пролог стал возможен благодаря исследованиям в области ес-

тественных языков, языков программирования и машинного пере-

вода.

Учеными был создан ряд систем, "понимающих" естествен-

ный язык. В 1979 году Ларри Харрисом из фирмы AI Corporation

была разработана система INTELLECT; она осуществляла взаимо-

действие с базами данных и информационными системами в об-

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

SCRIPTS, созданная фирмой Cognitive Systems,Inc, является

другим примером подобных систем. Программа NaturalLink,спро-

ектированная под руководством Харри Тэннанта в Texas

Instruments, служит интерфейсом с микрокомпьютерами. ELIZA,

естественно-языковый пакет, имитирующий работу психолога,

реагирует на ключевые слова, встречающиеся в предложениях

пациента, и дает запрограммированные рекомендации, основыва-

ясь на этих словах. Некоторое время ELIZA считалась одной из

наиболее серьезных программ в данной области. Автор ELIZA

Джозеф Вайценбаум, утверждал даже, что его детище в состоя-

нии заменить консультанта - человека.

Целью всех проводящихся в этой области искусственного

интеллекта работ, вне зависимости от различия в подходах к

решению проблемы, является создание программ, восприятие ес-

тественного языка которыми не сильно отличалась бы от восп-

риятия человека. Разрабатываемые программы, как правило, ра-

ботают с текстовым материалом, который либо вводится с кла-

виатуры, либо считывается специальным сканирующим устройст-

вом. Звуковые распознавание и синтез речи, по всей видимос-

ти, однако, будут играть все более возрастающую роль.

Анализ ключевых слов есть метод анализа предложений на

предмет наличия ключевых слов, которые может распознавать

компьютер. Ключевые слова становятся значениями объектов

предикатов. При этом не так важна грамматическая структура

предложения, так как программа не анализирует связей между

словами. Компьютер реагирует одинаково на различные варианты

входного текста; роль играет лишь наличие ключевых слов.

Хорошие результаты, как было показано, дает контекст-

но свободный анализ (КС-анализ). Построение любого естест-

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

мому грамматикой. Правила грамматики диктуют порядок следо-

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

языком предложения. В КС-грамматиках фразы классифицируются

в зависимости лишь от их внутренней структуры. В контекст-

но-зависимых грамматиках, наоборот, анализ конструкции зави-

сит от контекста, в котором стоит эта конструкция.

Например, допустимым является предложение

Мери читает книги.

Оно представляет уже знакомую субъектно-вербально-объектную

структуру. Смысл этого предложения можно понять, не обраща-

ясь ни к каким другим предложениям. Таким образом, оно под-

дается анализу как отдельная независимая единица.

Естественный язык, однако, содержит много примеров

контекстно-зависимых предложений. Рассмотрим предложение

Перед тем как он пошел на завтрак, Джон беседовал с Джо.

В данном предложении местоимение "он" неоднозначно. Не-

ясно, замещает ли оно "Джона", или замещает "Джо". Хотя язы-

ки землян вовсе не страдают от таких неоднозначностей, можно

создать язык, все предложения которого имеют смысл, понятный

из текста самого этого предложения, вне зависимости от кон-

текста. Именно такие предложения используются в подходе,

ориентированном на КС-грамматики.

Пролог является удобным средством использования подхо-

да, связанным с применением КС-грамматик, к обработке конст-

рукций естественного языка. КС-правила могут быть записаны в

виде утверждений Пролога. Задача распознавания предложений

сводится таким образом к задаче доказательства набора утвер-

ждений, задающих грамматическую структуру языка.

При синтаксическом анализе элементы предложений анализ-

пруются согласно грамматическим правилам. Такой анализ тре-

бует разбивки предложения на составные части: эта операция

проделывается посредством грамматического разбора предложе-

ния.

Техника грамматического разбора включает расширенный

разбор сети переходов, разбор конструкций снизу-вверх и

сверху-вниз. Расширенный разбор сети переходов состоит в

разбиении предложения на все меньшие и меньшие части до тех

пор, пока оно не будет разобрано целиком. При разборе сни-

зу-вверх анализу подвергаются все слова, начиная с самого ле-

вого и кончая самым правым. Действуя таким образом, можно

вывести любую возможную синтаксическую структуру. При анали-

зе сверху-вниз предложение анализируется, исходя из предпо-

ложения относительно его структуры. Техника анализа свер-

ху-вниз используется в одной из программ данной главы.

Прагматический анализ имеет дело с изучением того смыс-

ла, который люди вкладывают в предложения, а не того, кото-

рый выражают слова этого предложения сами по себе.Так,напри-

мер, ответом на вопрос "Почему Джон сегодня такой тихий ?"

является все же не "Сегодня он еще не говорил.". За этим

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

"Чем так сегодня обеспокоен Джон ?". Способность дать ответ

на этот, представляющий действительный интерес вопрос, а не

на его буквальную формулировку, требует наличия громадного

объема информации об особенностях человеческого восприятия,

родственных отношениях и чувствах людей. Такой подход к

проблеме общения на естественном языке является одним из на-

иболее сложных, поэтому, здесь пока трудно достчь каких-либо

значительных результатов.

11.3. Простейший интерфейс с использованием ключевых слов

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

интерфейс между машиной и человеком, правильно реагировать

на достаточно широкий класс вариаций запросов к системе.

Рассмотрим три таких запроса:

Расскажите мне о Джордже Вашингтоне.

Дайте мне информацию о Джордже Вашингтоне.

Кто такой Джордж Вашингтон?

Любое из этих предложений могло бы выступить в роли ко-

манды базы данных, запрашивающей сведения об этом выдающемся

человеке. Хотя предложения различаются по структуре, можно

сказать, что функционально они эквивалентны. Каждое из них

содержит имя Джордж Вашингтон. Программа может вычленить это

ключевое словосочетание и использовать его в качестве значе-

ния объекта утверждения БД. Поступая таким образом, можно

попытаться сконструировать несложный естественно-языковый

интерфейс с БД.

Определяя реакцию программы, следует уделить внимание

словам, стоящим в начале каждой фразы: расскажите (tell),

дайте (show), кто (who). Первые два из них можно трактовать

как запрос на всю имеющуюся в наличии информацию о Джордже

Вашингтоне. Третье, напротив, может указывать на то, что

пользователю нужна лишь часть этой информации. Как видно,

рассмотрение этих ключевых слов позволяет определить коли-

чество и вид выдаваемой информации.

При разработке простого естественно-языкового интерфей-

са можно принять следующие допущения относительно вводимых

командных предложений:

1. Структура команды не влияет на выбор используемых в ней

слов.

2. Для определения количества и характера запрашиваемой

пользователем информации требуется анализ всего лишь нес-

кольких ключевых слов.

Оба допущения можно пояснить на примере сравнения двух

таких командных предложений:

Опишите Джорджа Вашингтона.

Расскажите мне все, что известно о жизни и деятельности

Джорджа Вашингтона.

Второе предложение содержит много посторонних слов. Та-

кие слова игнорируются, ответ системы от них не зависит.

Главной задачей при разработке интерфейса, использующе-

го словарь ключевых слов, является анализ вводимых предложе-

ний с целью выделения ключей. Эта задача легко решается в

Турбо-Прологе. Процедура состоит из трех шагов:

1. Ввод команды как строки символов.

2. Преобразование этой строки в список слов.

3. Идентификация ключевых слов.

Первый шаг легко претворим в жизнь ввиду того, что

строка является базисным типом данных Турбо-Пролога. Второй

шаг требует написания правила, которое преобразует строку в

список. Такая операция может быть проделана при помощи вст-

роенного предиката Турбо-Пролога fronttoken. (См. разд.

N 6.13.)

Третий шаг может быть реализован двумя способами. Один

из них состоит в задании всех ключевых слов (всех их вариан-

тов, если таковые имеются) в утверждениях базы данных. Тогда

внутренние унификационные процедуры Турбо-Пролога смогут со-

поставить элементы предложения со значениями, взятыми из БД.

Если сопоставление удается, происходит переход к следующей

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

определяются позицией, которую они занимают в предложении.

Этот способ целиком основывается на частоте применения опре-

деленных грамматических конструкций. Так, например, ключевы-

ми могут считаться первое и последнее слова предложения, как

в вопросе "Где находится Бостон ?" Именно эти слова унифика-

ционные процедуры пытаются сопоставить с имеющимися в базе.

Так же, как и в первом случае, успешное сопоставление дает

программе возможность начать выполнение следующих шагов.

Этот вид анализа ключевых слов является примером очень

простого грамматического разбора команд пользователя. Если

количество ключевых слов будет достаточно большим, то из БД

можно будет извлекать более определенную и более подробную

информацию.

11.4. Программа создания списков

Познакомившись вкратце с основами метода анализа ключе-

вых слов, можно теперь попробовать спроектировать и написать

на Турбо-Прологе простую программу, анализирующую слова

входного предложения. Эта программа будет воспринимать ко-

мандные предложения, преобразовывать эти предложения в спи-

сок слов и печатать этот список на экране. Она также будет

выделять из списка последнее слово, а затем выдавать это

слово на экран.

Введенное пользователем предложение присваивается пере-

менной Sentence. Преобразование строки в список осуществля-

ется правилом convers, которое было приведено в гл. 6. Обра-

щение к convers имеет вид

convers(Sentence,List)

а само правило выглядит как

convers(Str,[Head|Tail]):-

fronttoken(Str,Head,Str1),!,

convers(Str1,Tail).

convers(_,[]).

В случае успешного выполнения convers переменная List

содержит список слов предложения. Каждый элемент списка -

слово.

Далее посредством ниже приведенного правила осуществля-

ется идентификация последнего элемента списка

last_element([Head],Last_element):-

Last_element = Head.

last_element([_|Tail],Last_element):-

last_element(Tail,Last_element).

Первый вариант этого рекурсивного правила присваивает

переменной Last_element последний элемент списка. Второй ва-

риант осуществляет передвижение в направлении конца списка.

Программа "Создание списка" (листинг 11.1) реализует

метод анализа ключевых слов. Она может послужить базисом для

создания других, более детально разработанных практических

программ. В ней используются средства Турбо-Пролога для ра-

боты с окнами. Применено также печатающее список правило

print_list, впервые встретившееся в гл. 6.

____________________________________________________________

Листинг 11.1

/* Программа: Создание списка. Файл: PROG1101.PRO */

/* Назначение: Преобразование входного предложения */

/* в список слов и извлечение из него */

/* последного слова. */

domains

str_list = symbol *

str = string

predicates

convers(str,str_list)

print_list(str_list)

do_convert_and_print

find_last_word(str_list)

last_element(str_list,sembol)

goal

do_convert_and_print.

clauses

/* правило, преобразующее входную строку в список */

/* слов */

convers(Str,[Head|Tail]):-

fronttoken(Str,Head,Str1),!,

convers(Str1,Tail).

convers(_,[]).

/* правило для печати списка */

print_list([]).

print_list([Head|Tail]):-

write(" ",Head), nl,

print_list(Tail).

/* правило для нахождения последнего элемента списка */

last_element([Head],Last_element):-

Last_element = Head.

last_element([_|Tail],Last_element):-

last_element(Tail,Last_element).

/* правило для нахождения и печати последнего */

/* элемента списка */

find_last_word(List) :-

last_element(List,LName),

nl, write(" Here is the last word : ",Lname), nl.

/* правило для целевого утверждкеия */

do_convert_and_print :-

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7," A List Maker ",1,10,23,40),

nl, write(" PLEASE TYPE IN A SENTENCE."),

cursor(3,6), readln(Sentence),

nl, write(" THE INPUT SENTENCE IS "), nl, nl,

write(" ",Sentence), nl,nl,

write(" THE OUTPUT LIST OF WORDS IS "), nl, nl,

convers(Sentence,List),

print_list(List),

find_last_word(List),

nl, write(" PRESS THE SPACE BAR."),

readchar(_),

clearwindow,

exit.

/***** конец программы *****/

____________________________________________________________

Представление о характере диалога с этой программой

можно получить из рис. 11.1. На ввод программе здесь подано

предложение

a man loves a woman

Обратим внимание на отсутствие в конце предложения точ-

ки '.'. Если бы точка стояла, то она трактовалась бы прог-

раммой как отдельный атом; и предикат last_element присвоил

бы точку переменной Last_element. Точка, следовательно, дол-

жна быть опущена, так как она не может внести никакой лепты

в процесс распознавания приказа.

* Упражнения

11.1. Запустите программу "Создание списка". В ответ на поя-

вившееся приглашение Goal: введите предложенные конструкции,

а затем проверьте выдачу. (Не забывайте опускать точку !)

When it rains it pours

(Когда идет дождь, льет)

Who is Joe Montana

(Кто такой Джо Монтана)

Tell me about spit_fire_87

(Расскажите мне о "спитфайере-87")

11.2. Поэкспериментируйте с программой, вводя свои собствен-

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

последнее слово печаталось заглавными буквами (Замечание:

Воспользуйтесь встроенным предикатом upper_lower). Запустите

на счет новый вариант программы и проверьте его.

11.3. Измените программу "Создание списка" так, чтобы из

списка выбирался не последний элемент, а первый. Проверьте

измененный вариант, запустив его на счет.

11.5. Программа идентификации ключевых слов

Как уже было сказано в предыдущем разделе, интерфейсная

система при идентификации слов может нуждаться в доступе к

БД. Сейчас мы покажем, как создать на Турбо-Прологе програм-

му, которая сопоставляет введенный пользователем текст с

данными, содержащимися в базе.

Запрос к БД в форме команды состоит из слов, некоторые

из которых должны быть распознаны как ключевые. Для этого

строка, содержащая текст команды, разделяется на слова, ко-

торые помещаются в список. Каждое слово списка используется

при попытке сопоставления его со значениями объектов опре-

деленных утверждений базы данных. Если сопоставление

удается, то эти значения присваиваются переменным, использу-

емым при вызове правил. Описанная техника демонстрируется на

примере программы "Ключевые слова".

Предположим, что необходимо создать интерфейс к "Фут-

больной базе данных", разработанной в гл. 9. Требуется выде-

лить фамилии игроков так, чтобы можно было давать ответы на

запросы о них. В этом случае программа должна содержать пра-

вила, извлекающие полное имя игрока из утверждения БД

dplayer и вычленять из этого имени (хранящегося как один

единый элемент данных) фамилию.

Для осуществления второй из перечисленных операций

программа должна преобразовывать полное имя игрока в список,

содержащий отдельно имя и фамилию игрока, а затем искать в

этом списке последний элемент. Наиболее существенная часть

реализующего эту операцию правила выглядит как

do_trick :-

dplayer(P_name,T_name,_,_,_,_,_,_),

D_name = P_name,

write(" ",D_name," ",T_name),nl,

convers(D_name,D_list),

last_element(D_list,L_name),

write(" Last name = ",L_name),nl,nl,

fail.

Полное имя игрока присваивается переменной D_name. Зна-

чение переменной обрабатывается правилом convers, которое

создает список, состоящий из имени и фамилии игрока. Правило

Last_element присваивает значение последнего элемента списка

переменной L_name.

Целиком программа "Ключевые слова" приведена на листин-

ге 11.2. Программа использует средства Турбо-Пролога для ра-

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

форме функции программы, а также распечатать ее ответы. Вы-

дача программы приведена на рис. 11.2. Отметим, что полное

имя игрока, его фамилия и название команды высвечиваются на

экране в специальном окне.

____________________________________________________________

Листинг 11.2

/* Программа: Ключевые слова. Файл: PROG1102.PRO */

/* Назначение: Получение списка объектов БД. */

domains

str_list = string *

p_name, t_name, pos, height, college = string

p_number, weight, nfl_exp = integer

database

dplayer(p_name, t_name, p_number, pos,

height, weight, nfl_exp, college)

predicates

do_trick

assert_database

clear_database

player(p_name, t_name, p_number, pos,

height, weight, nfl_exp, college)

convers(string,str_list)

last_element(str_list,string)

goal

assert_database,

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7," FootBall Database Query ",

2,10,22,50),

nl,nl,

do_trick,

write("Finished"),nl,

readchar(_),

clear_database.

clauses

assert_database :-

player(P_name,T_name,P_number,Pos,Ht,Wt,Exp,

College),

assertz( dplayer(P_name,T_name,P_number,Pos,Ht,

Wt,Exp,College) ),

fail.

assert_database :- !.

clear_database :-

retract( dplayer(_,_,_,_,_,_,_,_) ),

fail.

clear_database :- !.

do_trick :-

dplayer(P_name,T_name,_,_,_,_,_,_),

D_name = P_name,

write(" ",D_name," ",T_name),nl,

convers(D_name,D_list),

last_element(D_list,L_name),

write(" Last name = ",L_name),nl,nl,

fail.

do_trick :- write("no more names"),nl.

/* правило, преобразующие входную строку в список */

/* слов */

convers(Str,[Head|Tail]):-

fronttoken(Str,Head,Str1),!,

convers(Str1,Tail).

convers(_,[]).

/* правило для нахождения последнего элемента списка */

last_element([Head],Last_element):-

Last_element = Head.

last_element([_|Tail],Last_element):-

last_element(Tail,Last_element).

/* база данных */

player("Dan Marino","Miami Dolphins",13,"QB",

"6-3",215,4,"Pittsburgh").

player("Richart Dent","Chicago Bears",95,"DE",

"6-5",263,4,"Tennessee State").

player("Bernie Kosar","Cleveland Browns",19,"QB",

"6-5",210,2,"Miami").

player("Doug Cosbie","Dallas Cowboy",84,"TE",

"6-6",235,8,"Santa Clara").

player("Mark Malone","Pittsburgh Steelers",16,"QB",

"6-4",223,7,"Arizona State").

/***** конец программы *****/

____________________________________________________________

* Упражнения

11.4. Запустите на счет программу "Ключевые слова". Сверьте

выдачу на экран монитора с той, что приведена на рис. 11.2.

Добавьте в БД сведения о нескольких новых игроках.

11.5. Внесите изменения в правило do_trick так, чтобы на эк-

ран помимо других данных выводится показатель стажа выступ-

лений игрока nfl_experience. Модифицируйте затем программу,

чтобы на экране печаталась лишь фамилия игрока и его стаж

выступлений.

11.6. Переделайте программу таким образом, чтобы БД програм-

мы располагалась на диске и считывалась в память при запус-

ке. (Возможно, следует при этом еще раз обратиться к прог-

рамме "Университетский футбол" из гл. 9.)

11.6. Программа естественно-языкового интерфейса с футболь-

ной базой данных

Программа "Создание списка" продемонстрировала исполь-

зование анализа ключевых слов при обработке зпросов пользо-

вателя, а программа "Ключевые слова" показала, как ключевое

слово может быть извлечено из базы данных. Теперь мы соеди-

ним два этих приема и создадим программу естественно-языко-

вого интерфейса с БД.

Назначением такой программы явится поиск в БД заданной

пользователем фамилии игрока. Если на первой позиции в зап-

росе стоят слова Tell, Show или Who, а на последней - фами-

лия игрока, то внутренние унификационные процедуры Тур-

бо-Пролога произведут быстрый поиск игрока с соответствующей

фамилией в базе. Если такой игрок будет найден, то сведения

о нем высветятся на экране дисплея. В случае отсутствия иг-

рока пользователь будет проинформирован о том, что нужных

данных нет в наличии.

На рис. 11.3 приведена структурная схема программы "Ин-

терфейс с футбольной базой данных". Главный модуль,

do_query, вызывает шесть других. Первый и последний из этой

шестерки осуществляют соответственно загрузку и очистку БД.

Второй модуль, convers, преобразует в список входную строку.

Следующие два модуля first_element и last_element выделяют

из входного предложения первое и последнее ключевые слова.

Первое из них анализируется на принадлежность к набору до-

пустимых программой ключевых слов, второе (последнее слово

предложения) задает фамилию футболиста.

Пятый модуль из вызываемых do_query - это do_right_

form. Он отвечает за проверку правильности первого ключевого

слова, которое должно быть либо SHOW, либо TELL, либо WHO.

Второе ключевое слово передается модулю access_database, ко-

торый в свою очередь вызывает модуль search_player для поис-

ка в БД игрока с заданной фамилией. search_player использует

два других модуля, convers и last_element, для идентификации

фамилии игрока.

Главный модуль имеет вид

do_query :-

assert_database,

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7,"",1,3,4,71),

cursor(1,22), write("PRO FOOTBALL DATABASE"),

makewindow(3,7,7," Input Info ",6,3,6,37),

repeat, nl,

write(" Please type in your question."),

cursor(3,2), readln(Sentence),

makewindow(4,7,7," List Maker ",6,42,6,32),

convers(Sentence,List),

first_element(List,Kname),

last_element(List,Lname),

do_right_form(Kname,Lname),

clear_database.

Встречающиеся в этом модуле правила convers и

last_element в точности повторяют одноименные правила из

предыдущей программы. Правило first_element извлекает первый

элемент из списка, полученного из входного предложения.

first_element([Head|_],Fname):-

Fname = Head.

Модуль do_right_form проверяет первое ключевое слово и

извлекает из БД фамилию игрока:

do_right_form(Kname,Lname) :-

keyword(Kname),

nl, write(" THE KEY WORDS ARE "), nl,

nl, write(" ",Kname," ",Lname),

makewindow(5,7,7," Player Info ",12,3,12,71),

access_database(Lname),

nl, write(" ANY KEY CONTINUES."),

readchar(_),

removewindow,

gotowindow(4),

removewindow,

gotowindow(3),

clearwindow,!,

fail.

Проверка ключевого слова осуществляется при помощи вы-

зова правила keyword:

keyword(Key) :-

upper_lower(Upkey,Key),

Upkey = "SHOW",!.

Этот предикат успешен, если верхнерегистровый эквива-

лент первого слова команды есть SHOW. Аналогичные варианты

правила написаны и для ключевых слов WHO и TELL. Расширение

словарного запаса системы не составляет практически никакого

труда.

Если же выполнение keyword заканчивается неуспешно, то

испытываются другие варианты do_right_form:

do_right_form(Kname,_) :-

Kname="Done",!,

exit.

do_right_form(Kname,_) :-

nl, write(" This keyword is unknown:"), nl,

nl, write(" ",Kname),

nl, write(" Press any key to try again."),

readchar(_),

removewindow,

clearwindow,!,

fail.

Первый из приведенных вариантов вызывает завершение ра-

боты программы; второй информирует пользователя об обнаруже-

нии незнакомого ключевого слова.

Первый вариант правила do_right_form вызывает модуль

access_database, а тот - модуль search_player, ищущий в БД

игрока по его фамилии.

Модуль search_player выглядит следующим образом:

search_player(Lname) :-

dplayer(Name,Team,Number,Position,

Height,Weight,NFL_Exp,College),

Team_name = Name,

convers(Team_name,Dlist),

last_element(Dlist,Dname),

Lname = Dname,

nl, write("Available information:"),

nl, nl, write(" ",Name," is a player "),

write("on the ",Team," team."),

nl, write(" His number is ",Number),

write(" and his position is ",Position,"."),

nl, write(" His weight and height are ",Weight),

write(" lb. and ",Height," ft-inch."),

nl, write(" He has ",NFL_Exp,

" years of NFL experience."),

nl, write(" He is a graduate of ",College,"."),

nl, !.

search_player(_) :-

nl, nl,

write("That player is not in the database."),

nl.

В правиле search_player утверждения БД dplayer включают

восемь объектов. Среди них есть переменная Name, определяю-

щая полные имена игроков из БД. Переменная Temp_name исполь-

зуется для работы с копией значения Name. Правило convers

преобразует содержащую полное имя игрока строку в список

слов Dlist. Правило last_element извлекает из списка фамилию

игрока.

Программа "Интерфейс с футбольной базой данных" (лис-

тинг 11.3) реализует рассмотренный проект. Программа исполь-

зует несколько окон; графические средства Турбо-Пролога де-

лают это достаточно сложное представление информации простым

в реализации и весьма эффективным.

____________________________________________________________

Листинг 11.3

/* Программа: Естественно-языковый интерфейс */

/* с футбольной БД. */

/* Файл: PROG1103.PRO */

/* Назначение: Создание естественно-языкового ин- */

/* терфейса к БД. */

domains

str_list = symbol *

str = string

p_name, t_name, pos, height, college = string

p_number, weight, nfl_exp = integer

database

dplayer(p_name, t_name, p_number, pos,

height, weight, nfl_exp, college)

predicates

repeat

do_query

assert_database

clear_database

player(p_name, t_name, p_number, pos,

height, weight, nfl_exp, college)

convers(string,str_list)

first_element(str_list,string)

last_element(str_list,string)

access_database(string)

search_player(string)

do_right_form(string,string)

keyword(string)

goal

do_query.

clauses

repeat.

repeat :- repeat.

assert_database :-

player(P_name,T_name,P_number,Pos,Ht,Wt,Exp,

College),

assertz( dplayer(P_name,T_name,P_number,Pos,Ht,

Wt,Exp,College) ),

fail.

assert_database :- !.

clear_database :-

retract( dplayer(_,_,_,_,_,_,_,_) ),

fail.

clear_database :- !.

/* правило, преобразующие входную строку в список */

/* слов */

convers(Str,[Head|Tail]):-

fronttoken(Str,Head,Str1),!,

convers(Str1,Tail).

convers(_,[]).

/* правило для нахождения первого элемента списка */

first_element([Head|_],Fname):-

Fname = Head.

/* правило для нахождения последнего элемента списка */

last_element([Head],Last_element):-

Last_element = Head.

last_element([_|Tail],Last_element):-

last_element(Tail,Last_element).

/* доступ к базе данных и печать информации */

access_database(Lname) :-

search_player(Lname).

/* поиск игрока */

search_player(Lname) :-

dplayer(Name,Team,Number,Position,

Height,Weight,NFL_Exp,College),

Team_name = Name,

convers(Team_name,Dlist),

last_element(Dlist,Dname),

Lname = Dname,

nl, write("Available information:"),

nl, nl, write(" ",Name," is a player "),

write("on the ",Team," team."),

nl, write(" His number is ",Number),

write(" and his position is ",Position,"."),

nl, write(" His weight and height are ",Weight),

write(" lb. and ",Height," ft-inch."),

nl, write(" He has ",NFL_Exp,

" years of NFL experience."),

nl, write(" He is a graduate of ",College,"."),

nl, !.

search_player(_) :-

nl, nl,

write("That player is not in the database."),

nl.

/* правило для целевого утверждения */

do_query :-

assert_database,

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7,"",1,3,4,71),

cursor(1,22), write("PRO FOOTBALL DATABASE"),

makewindow(3,7,7," Input Info ",6,3,6,37),

repeat, nl,

write(" Please type in your question."),

cursor(3,2), readln(Sentence),

makewindow(4,7,7," List Maker ",6,42,6,32),

convers(Sentence,List),

first_element(List,Kname),

last_element(List,Lname),

do_right_form(Kname,Lname),

clear_database.

/* правило для проверки ключевого слова */

do_right_form(Kname,Lname) :-

keyword(Kname),

nl, write(" THE KEY WORDS ARE "), nl,

nl, write(" ",Kname," ",Lname),

makewindow(5,7,7," Player Info ",12,3,12,71),

access_database(Lname),

nl, write(" ANY KEY CONTINUES."),

readchar(_),

removewindow,

gotowindow(4),

removewindow,

gotowindow(3),

clearwindow,!,

fail.

do_right_form(Kname,_) :-

Kname="Done",!,

exit.

/* информация о ключевых словах */

do_right_form(Kname,_) :-

nl, write(" This keyword is unknown:"), nl,

nl, write(" ",Kname),

nl, write(" Press any key to try again."),

readchar(_),

removewindow,

clearwindow,!,

fail.

/* проверка правильности ключевых слов */

keyword(Key) :-

upper_lower(Upkey,Key),

Upkey = "SHOW",!.

keyword(Key) :-

upper_lower(Upkey,Key),

Upkey = "WHO",!.

keyword(Key) :-

upper_lower(Upkey,Key),

Upkey = "TELL",!.

/* Футбольная база данных */

player("Dan Marino","Miami Dolphins",13,"QB",

"6-3",215,4,"Pittsburgh").

player("Richart Dent","Chicago Bears",95,"DE",

"6-5",263,4,"Tennessee State").

player("Bernie Kosar","Cleveland Browns",19,"QB",

"6-5",210,2,"Miami").

player("Doug Cosbie","Dallas Cowboy",84,"TE",

"6-6",235,8,"Santa Clara").

player("Mark Malone","Pittsburgh Steelers",16,"QB",

"6-4",223,7,"Arizona State").

/***** конец программы *****/

_____________________________________________________________

Пример диалога с программой "Интерфейс с футбольной ба-

зой данных" можно видеть на рис. 11.4. Окно в верхней части

экрана содержит название БД. Окно Input Info предназначено

для ввода команды пользователя, в окне List Maker приводятся

приводятся значения обоих ключевых слов. Окно Player Info

содержит выдачу всей имеющейся информации об игроке. Заме-

тим, что эта информация выводится в виде законченных предло-

жений, что делает программу еще более удобной для пользова-

теля.

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

увидеть, что ни размер БД, ни увеличение количества ключевых

слов не влияют существенно на время работы внутренних унифи-

кационных процедур Турбо-Пролога, работа которых протекает

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

куда больше времени, чем любой другой процесс в системе.

* Упражнения

11.7. Введите и запустите на счет программу "Интерфейс с

футбольной базой данных". По выдаче приглашения введите при-

веденные ниже предложения и проверьте результат работы прог-

раммы. (Ввод каждого предложения должен вызвать печать на

экране занесенных в базу данных.)

Tell me about Dan Marino

Who is Mark Malone

Введите теперь другие команды и посмотрите на реакцию

системы. (Одно предложение должно породить ответ

That player is not in the database.

(Cведений об этой игроке в БД нет)

а другое -

This keyword is unknown:

(Неопознанное ключевое слово).

Tell me about Joe Montana

How tall is Chip Banks

11.8. Объедините программу "Интерфейс с футбольной базой

данных" с программой "Футбольная база данных" из гл. 9, так,

чтобы в результирующей программе в главном меню появилась

опция, позволяющая перейти в режим естественно-языкового ди-

алога с базой данных. (Замечание: В этой работе удобно вос-

пользоваться структурной схемой программы "Футбольная база

данных". Схема поможет определить то место, куда нужно доба-

вить новые программные модули.) Запустите на счет созданную

программу, задайте опцию Natural Language Interface. Посмот-

рите, что получилось.

11.7. Контекстно-свободный анализ

КС-анализ начинается с построения модели предложения.

Ввиду того, что существует множество типов предложений, со-

ответственно существует и множество различных моделей для их

представления. В настоящем разделе будут использоваться лишь

очень простые модели, которые, однако, годны для довольно

большого числа обычных предложений.

11.7.1. Простейшие модели предложений для КС-анализа

С точки зрения КС-анализа предложение можно рассматри-

вать как некий список слов:

тело предложения = [dogs,bark]

( [собаки,лают] )

тело предложения = [Tom,loves,Lana]

( [Том,любит,Лану] )

тело предложения = [Some,boys,love,furry,dogs]

( [Некоторые,люди,любят,лохматых,собак] )

Каждое предложение должно вдобавок соответствовать не-

которой модели. Эти модели позволяют реализовать на Тур-

бо-Прологе разбор предложений. Модели могут быть достаточно

простыми, такими, каковыми являются приведенные ниже.

Слова базисного декларативного предложения, размещенные

слева направо, согласуются со следующей синтаксической мо-

делью.

предложение = группа существительного, группа глагола

Эту модель можно немного детализировать, так что каждый

из представленных элементов будет иметь свои составляющие:

группа существительного = [определение,][прилагательное,]

существительное | местоимение |

группа глагола = [наречие,] непереходный глагол |

[наречие,] переходный глагол, группа существительного

В квадратные скобки здесь заключены необязательные чле-

ны предложения; запятые разделяют компоненты группы сущест-

вительного и группы глагола. Вертикальные линии указывают на

возможность альтернативы. Так, например, группа существи-

тельного может состоять либо из существительного (перед ко-

торым, возможно, стоит прилагательное), либо из местоимения

(перед которым также может стоять прилагательное).

Ваше предложение может и не содержать всех необязатель-

ных частей, но в модели они представлены, чтобы предусмот-

реть все возможные случаи.

Большинство наиболее часто употребимых предложений со-

отвествует данной модели. Это можно продемонстрировать на

следующих примерах:

Sue loves color_tv (Cью нравится цветной телевизор)

Tom hates herbal_tea (Том ненавидит травяной чай)

Sam eats fries (Сэм ест жаркое)

Имея некоторый набор существительных и глаголов, можно

как анализировать, так и составлять самостоятельно предложе-

ния данного типа. Анализ предложения заключается в определе-

нии того, что первое слово является существительным, второе

- глаголом, третье - еще одним существительным. Если выясня-

ется, что структура предложения корректна, значения состав-

ляющих предложение слов могут послужить сигналом программе

предпринять определенные действия. Данный метод полезен при

решениии таких задач, как разработка пользовательских интер-

фейсов и систем управления роботами. Из следующего раздела

вы узнаете, как на Турбо-Прологе пишется программа, выполня-

ющая простой лексический анализ.

11.7.2. Программа лексического анализатора предложений

Рассмотрим маленький гипотетический мир, в котором бу-

дут жить наши персонажи: Сэм, Сью и Том. Их жизнь очень не-

замысловата: все возможные действия в этом мире можно выра-

зить пятью глаголами. Сэм и Сью питаются гамбургерами, жар-

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

случаются аллергии и головные боли; они любят друг друга, а

заодно и Тома. Все существительные и глаголы этого крошечно-

го мирка приведены в табл. 11.1.

____________________________________________________________

Таблица 11.1. Существительные и глаголы

Существительные:

Люди Пища Хвори Имущество

sam hamburger head_ache color_tv

sue fries allergy

water

herbal_tea

Глаголы:

Действия

eats

loves

gives

hates

helps

____________________________________________________________

Собранные в таблице слова являются объектами утвержде-

ний БД и помечены там либо как существительные, либо как

глаголы. Предложение являет из себя высказывание о мире Сэма

и Сью. Программа проверяет синтаксис предложения, а также

принадлежность к заданному набору использованных в предложе-

нии слов. Если обе проверки дают удовлетворительные резуль-

таты, предложение считается "корректным"; в противном случае

оно "некорректно".

На рис. 11.5 приведена структурная схема программы

"Лексический анализатор". Главным модулем этой программы яв-

ляется правило show_the_work. Он вызывает модуль do_windows,

который создает три окна, и модуль print_vocabulary, который

распечатывает словарь программы.

Модуль print_sentences анализирует предложения, запи-

санные в утверждениях БД sentence. Предложения хранятся в

виде списков. Этот модуль вызывает другой, show_sentence,

который извлекает предложения из базы. Еще один модуль

check_word проверяет допустимость встретившихся в предложе-

нии слов. Если все слова допустимы программой, предложение

считается воспринятым; в противном случае программа выдает

сообщение

??? Not legal sentence ???

(Предложение некорректно.)

Главный модуль программы записан в виде

show_the_work :-

do_windows,

print_vocabulary,

print_sentences.

Модуль print_vocabulary непосредственно печатает список

всех допустимых существительных и глаголов. В практических

применениях синтаксического анализатора этот список может

стать очень большим.

Модуль print_sentences содержит следующие предикаты:

print_sentences :-

gotowindow(3),

nl, write(" Sentence Analysis"),

nl, nl,

write(" sentence = <subject,verb,object>"),

nl, nl,

write(" Here are the sentences."),

nl, nl, nl,

show_sentence.

Доступ к утверждениям sentence осуществляет модуль

show_sentence:

show_sentence :-

sentence([W1,W2,W3]),

write(W1," ",W2," ",W3),

check_word(W1,W2,W3),

nl, fail.

show_sentence :-

cursor(19,5),

write(" Press the space bar."),

readchar(_),

exit.

Этот модуль определяет, насколько корректна структура

содержащегося в БД предложения.

Чтобы проверить достоверность слов, составляющих пред-

ложение, вызывается модуль chech_word, который выглядит сле-

дующим образом:

check_word(W1,W2,W3) :-

noun(W1), verb(W2), noun(W3), !.

check_word(_,_,_) :-

nl ,write(" ??? Not legal sentence ???"), nl.

Он пытается сопоставить с объектами утверждений noun

первое слово предложения. Если это удается, то правило дока-

зано. Аналогичные попытки предпринимаются также со вторым и

третьим словами, при этом используются утверждения verb и

noun соответственно. Если неуспешно хотя бы одно из трех со-

поставлений, то неуспешен и весь первый вариант правила

check_word. В этом случае происходит откат ко второму вари-

анту этого же правила, что приводит к печати сообщения

??? Not legal sentence ???

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

Целиком программа "Лексический анализатор предложений"

приведена на листинге 11.4.

____________________________________________________________

Листинг 11.4

/* Программа: Лексический анализатор предложений */

/* Файл: PROG1104.PRO */

/* Назначение: Разбор предложений при помощи прос- */

/* тейшего лексического анализатора. */

domains

str_seq = string *

database

noun(string)

verb(string)

predicates

show_the_work

do_windows

print_vocabulary

print_sentences

show_sentence

check_word(string,string,string)

sentence(str_seq)

goal

show_the_work.

clauses

/* правило - цель */

show_the_work :-

do_windows,

print_vocabulary,

print_sentences.

/* правила для создания окон */

do_windows :-

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7," Vocabulary ",2,40,22,34),

makewindow(3,7,7," Sentences ",2,2,22,36).

/* правило для печати словаря */

print_vocabulary :-

gotowindow(2),

nl,

write(" Legal Nouns"), nl, nl,

write(" sam"), nl,

write(" sue"), nl,

write(" tom"), nl,

write(" hamburger"), nl,

write(" fries"), nl,

write(" water"), nl,

write(" herbal_tea"), nl,

write(" color_tv"), nl,

write(" head_ache"), nl,

write(" allergy"), nl, nl,

write(" Legal Verbs"), nl, nl,

write(" eats"), nl,

write(" loves"), nl,

write(" gives"), nl,

write(" hates"), nl,

write(" helps").

/* правило для печати предложения */

print_sentences :-

gotowindow(3),

nl, write(" Sentence Analysis"),

nl, nl,

write(" sentence = <subject,verb,object>"),

nl, nl,

write(" Here are the sentences."),

nl, nl, nl,

show_sentence.

/* правило для проверки предложений */

show_sentence :-

sentence([W1,W2,W3]),

write(W1," ",W2," ",W3),

check_word(W1,W2,W3),

nl, fail.

show_sentence :-

cursor(19,5),

write(" Press the space bar."),

readchar(_),

exit.

/* правило для сопоставления слов предложения со */

/* словами из базы данных */

check_word(W1,W2,W3) :-

noun(W1), verb(W2), noun(W3), !.

check_word(_,_,_) :-

nl ,write(" ??? Not legal sentence ???"), nl.

/* база данных (словарь) */

/* существительные */

noun(sam).

noun(sue).

noun(tom).

noun(hamburger).

noun(fries).

noun(water).

noun(herbal_tea).

noun(color_tv).

noun(head_ache).

noun(allergy).

/* глаголы */

verb(eats).

verb(loves).

verb(gives).

verb(hates).

verb(helps).

/* входные предложения */

sentence([sam,eats,french_fries]).

sentence([tom,hates,herbal_tea]).

sentence([sue,loves,color_tv]).

sentence([herbal_tea,helps,head_ache]).

sentence([hamburger,gives,allergy]).

/***** конец программы *****/

____________________________________________________________

Программа демонстрирует использование методик, расмот-

ренных в предыдущих разделах главы. Отметим, что для вывода

результатов анализа программа создает два окна.

Пример диалога с программой показан на рис. 11.6. Спи-

сок всех допустимых существительных и глаголов высвечивается

в правом окне. В левом приводятся результаты разбора предло-

жений. Первое из содержащихся в БД предложений Sam eats

french_fries некорректно. К миру Сэма относится слово fries,

но отнюдь не french_fries. Другими словами, french_fries не

есть существительное из словаря. Остальные четыре предложе-

ния являются корректными.

Настоящая программа есть пример надлежащего использова-

ния средств Турбо-Пролога для грамматического разбора пред-

ложения и проверки его на соответствие принятой модели. Во

время работы программы не возникает каких-либо заминок.

Программа очень эффективна при наличии большого словарного

запаса или при сложной грамматике.

* Упражнения

11.9. Считайте программу "Лексический анализатор предложений

в окно редактора Турбо-Пролога. Измените первое предложение,

заменив в нем некорректное слово на слово из словаря. Запус-

тите на счет измененный вариант программы и посмотрите, что

получится.

11.10. Модифицируйте программу "Лексический анализатор пред-

ложений", так чтобы появилась возможность вводить новые

предложения с клавиатуры. Введите несколько предложений, как

корректных, так и некорректных. Убедитесь в том, что прог-

рамма работает должным образом. Входные предложения должны

записываться в нормальной форме, а не в виде списка. Запус-

тите программу на счет. Попробуйте ввести с клавиатуры сле-

дующие предложения (все они имеют допустимую структуру):

Sue helps Tom

color_tv gives head_ache

11.7.3. Программа КС-анализатора предложений

Процедура грамматического разбора предложений уже была

кратко описана в настоящей главе. Программа "Синтаксический

анализатор предложений", представленная на листинге 11.5 ре-

ализует технику разбора предложений контекстно-свободной

грамматики.

____________________________________________________________

Листинг 11.5

/* Программа: Синтаксический анализатор предложений. */

/* Файл: PROG1105.PRO */

/* Назначение: Демонстрация работы синтаксического */

/* анализатора предложений. */

/* Указания: Запустите пограмму на счет. */

/* Цель задана внутри программы. */

domains

Tklist = String *

Sentence = sentence(Noun_phrase,Verb_phrase)

Noun_phrase = noun_phrase(Determiner,String,

Relative_clause)

Relative_clause = nil ; relcl(String,Verb_phrase)

Determiner = nil ; determ(String)

Verb_phrase = verb(String) ; verbp(String,

Noun_phrase)

database

noun(string)

verb(string)

dete(string)

rela(string)

predicates

toklist(String,Tklist)

match(String)

nphrase(Tklist,Tklist,Noun_phrase)

determiner(Tklist,Tklist,Determiner)

sentex(Tklist,Tklist,Sentence)

relclause(Tklist,Tklist,Relative_clause)

vphrase(Tklist,Tklist,Verb_phrase)

do_dcg

analyse_it

request_a_sentence

analyse_sentence(string)

print_list(Tklist)

process(integer)

goal

do_dcg.

clauses

/* правило для целевого утверждения */

do_dcg :-

makewindow(1,7,7,"",0,0,25,80),

makewindow(2,7,7," Main Window ",1,0,22,39),

nl, nl, write(" SENTENCE ANALIZER"),

nl, nl, write(" 1. Analize a sentence"),

nl, nl, write(" 2. Exit the program"),

nl, nl, write(" Please enter: 1 or 2. "),

readint(Choice),

process(Choice),

do_dcg.

process(1) :- analyse_it.

process(2) :- exit.

/* интерфейс с пользователем */

analyse_it :-

makewindow(3,7,7," Sentence Analizer",2,4,23,72),

nl, write(" This program analizes"),

write(" a sentence in a CFG Model."),nl,

nl, write(" "),

write("sentense = noun-phrase + verb-phrase"),

request_a_sentence.

analyse_it :- removewindow.

request_a_sentence :-

makewindow(4,7,7," Dialogue Window ",8,2,4,38),

nl, write("Type in sentence."),

nl, readln(Line),

analyse_sentence(Line), !,

request_a_sentence.

analyse_sentence(Line) :-

makewindow(5,7,7," Result Window ",8,41,16,38),

toklist(Line,Tklist),

sentex(Tklist,_,Sent_model),

nl, write("Input Sentence : ",Line), nl, nl,

nl, write("List of words :"), nl, nl,

print_list(Tklist),

nl, write("The sentence model is:"), nl,

nl, write(Sent_model).

analyse_sentence(_).

print_list([]).

print_list([Head|Tail]) :-

write(" ",Head), nl,

print_list(Tail).

/* правила анализа */

toklist(Str,[Token|Tklist]) :-

fronttoken(Str,Token,Str1),

match(Token),!,

toklist(Str1,Tklist).

toklist(_,[]).

match(W) :- noun(W),!. match(W) :- dete(W),!.

match(W) :- rela(W),!. match(W) :- verb(W),!.

match(W) :- write(W," - is not recognized."),

nl, write(" Press the SPACE bar."),

readchar(_).

sentex(Tklist,Tklist2,sentence(Noun_phrase,

Verb_phrase)) :-

nphrase(Tklist,Tklist1,Noun_phrase),

vphrase(Tklist1,Tklist2,Verb_phrase), !.

sentex(_,_,_) :-

write(" That sentence is not recognized."),

nl, fail.

nphrase(Tklist,Tklist2,

noun_phrase(Determiner,Noun,

Relative_clause) ) :-

determiner(Tklist,[Noun|Tklist1],Determiner),

noun(Noun),

relclause(Tklist1,Tklist2,Relative_clause).

determiner([Determiner|Tklist],Tklist,

determ(Determiner)) :-

dete(Determiner).

determiner(Tklist,Tklist,nil).

relclause([Relative|Tklist],Tklist1,

relcl(Relative,Verb_phrase)) :-

rela(Relative),

vphrase(Tklist,Tklist1,Verb_phrase).

relclause(Tklist,Tklist,nil).

vphrase([Verb|Tklist],Tklist1,verbp(Verb,

Noun_phrase)) :-

verb(Verb),

nphrase(Tklist,Tklist1,Noun_phrase).

vphrase([Verb|Tklist],Tklist,verb(Verb)) :-

verb(Verb).

/* база данных */

noun("Lana"). noun("Tom"). noun("cat"). noun("dog").

dete("a"). dete("an"). rela("that"). rela("who").

verb("loves"). verb("hates"). verb("likes").

verb("sleeps"). verb("dislikes"). verb("scares").

/***** конец программы *****/

____________________________________________________________

Синтаксическая структура КС-грамматики описана в разде-

ле программы domains:

Sentence = sentence(Noun_phrase,Verb_phrase)

Noun_phrase = noun_phrase(Determiner,String,

Relative_clause)

Relative_clause = nil ; relcl(String,Verb_phrase)

Determiner = nil ; determ(String)

Verb_phrase = verb(String) ; verbp(String,

Noun_phrase)

Раздел программы database содержит утверждения, храня-

щие существительные, глаголы, определители из словаря прог-

раммы, а также относительные местоимения. Их описания пре-

дельно просты:

noun(string)

verb(string)

dete(string)

rela(string)

Основные функции программы можно кратко сформулировать

следующим образом:

1. Ввод предложений пользователя осуществляется с клавиа-

туры. За эту операцию отвечает правило request_a_sentence:

request_a_sentence :-

makewindow(4,7,7," Dialogue Window ",8,2,4,38),

nl, write("Type in sentence."),

nl, readln(Line),

analyse_sentence(Line), !,

request_a_sentence.

2. Правило analyze_sentence вызывает правило toklist, фор-

мирующее список слов (атомов) из входной строки. Затем вызы-

вается правило sentex; это правило строит модель предложе-

ния. Целиком analyze_sentence выглядит так:

analyse_sentence(Line) :-

makewindow(5,7,7," Result Window ",8,41,16,38),

toklist(Line,Tklist),

sentex(Tklist,_,Sent_model),

nl, write("Input Sentence : ",Line), nl, nl,

nl, write("List of words :"), nl, nl,

print_list(Tklist),

nl, write("The sentence model is:"), nl,

nl, write(Sent_model).

analyse_sentence(_).

3. Правило toklist строит список слов и одновременно про-

веряет наличие этих слов в базе данных. Первое слово входно-

го предложения присваивается переменной Token при помощи

предиката fronttoken. Затем правило match просматривает ут-

верждения БД и пытается сопоставить слово из предложения с

одним из слов, содержащихся в базе, устанавливая таким обра-

зом, к какой части речи это слово относится. Если значение

Token несопоставимо ни с одним словом словаря, то пользова-

тель получает сообщение <word>-is not recognized (<cлово> не

опознано). Дальнейший анализ в этом случае не производится,

а toklist завершается неуспехом. Таким образом для успешного

завершения toklist необходимо присутствие в БД слов, исполь-

зованных в предложении.

toklist(Str,[Token|Tklist]) :-

fronttoken(Str,Token,Str1),

match(Token),!,

toklist(Str1,Tklist).

toklist(_,[]).

match(W) :- noun(W),!. match(W) :- dete(W),!.

match(W) :- rela(W),!. match(W) :- verb(W),!.

match(W) :- write(W," - is not recognized."),

nl, write(" Press the SPACE bar."),

readchar(_).

4. Правило sentex отвечает за построение модели предложе-

ния. В процессе работы оно вызывает правило nphrase, строя-

щее группу существительного, и правило vphrase, строящее

группу глагола:

sentex(Tklist,Tklist2,sentence(Noun_phrase,

Verb_phrase)) :-

nphrase(Tklist,Tklist1,Noun_phrase),

vphrase(Tklist1,Tklist2,Verb_phrase), !.

sentex(_,_,_) :-

write(" That sentence is not recognized."),

nl, fail.

5. nphrase использует в работе два правила. Одно из них -

правило determiner; оно работает с определителями, Другое -

правило relclause, Если сопоставление удается, правило ус-

пешно; не удается - неуспешно.

nphrase(Tklist,Tklist2,

noun_phrase(Determiner,Noun,

Relative_clause) ) :-

determiner(Tklist,[Noun|Tklist1],Determiner),

noun(Noun),

relclause(Tklist1,Tklist2,Relative_clause).

determiner([Determiner|Tklist],Tklist,

determ(Determiner)) :-

dete(Determiner).

determiner(Tklist,Tklist,nil).

relclause([Relative|Tklist],Tklist1,

relcl(Relative,Verb_phrase)) :-

rela(Relative),

vphrase(Tklist,Tklist1,Verb_phrase).

relclause(Tklist,Tklist,nil).

6. Правило vphrase для сопоставления возможных глагольных

групп использует правило nphrase. Заметим, что nphrase в

свою очередь использует vphrase, как это видно из пункта 4.

Два варианта правила vphrase - это

vphrase([Verb|Tklist],Tklist1,verbp(Verb,

Noun_phrase)) :-

verb(Verb),

nphrase(Tklist,Tklist1,Noun_phrase).

vphrase([Verb|Tklist],Tklist,verb(Verb)) :-

verb(Verb).

Программа содержит также модули, реализующие интерфейс

с пользователем. Эти модули используют средства Турбо-Про-

лога для работы с окнами.

На рис. 11.7 показан пример диалога пользователя с

программой "Синтаксический анализатор". Для ввода предложе-

ний программа создает окно диалога (Dialog Window). Резуль-

таты разбора высвечиваются в окне результатов (Result

Window). В случае корректности введенного предложения выдача

содержит его текст, список содержащихся в нем слов, а также

модель предложения.

* Упражнения

11.11. Переделайте программу "Анализатор предложений" так,

чтобы в качестве подсказки она выдавала в специальном окне

список всех допустимых слов.

11.8. Заключение

В настоящей главе вы познакомились с несколькими раз-

личными подходами к решению проблемы общения с машиной на

естественном языке. Ввиду ее сложности каждый из подходов

имеет весьма ограниченную область применения. Красота чело-

веческого языка, его нюансы и утонченные вариации делают эту

проблему предметом непрекращающихся исследований и разрабо-

ток.

Подход, связанный с анализом ключевых слов, вполне

уместен при создании простейших естественно-языковых интер-

фейсов баз данных. Техника программирования естественно-язы-

ковых интерфейсов, использующих в работе ключевые слова, бы-

ла продемонстрирована на примере трех программ . Вы также

имели возможность убедиться в том, что модель контекст-

но-свободного анализа предложений позволяет создать удобные

и достаточно нетривиальные средства разбора предложений.

Приведенные простые, но вместе с тем эффективные программы

лексического и синтаксического анализаторов могут быть рас-

ширены для анализа столь сложных структур, сколь это требу-

ется разработчику.

Программы данной главы отражают основные шаги в области

решения проблемы общения с компьютером на естественном язы-

ке. Программы наделяются способностью воспринимать и генери-

ровать информацию в виде конструкций, достаточно похожих на

язык человеческого общения. В этих программах находят приме-

нение многие средствf Турбо-Пролога. Внутренние возможности

этой системы делают реализацию языковых анализаторов однов-

ременно достаточно очевидной и эффективной.

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