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

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

.pdf
Скачиваний:
11
Добавлен:
12.11.2022
Размер:
4.14 Mб
Скачать

an_number(Z) -->

an_number(0, X), "-", {Z is -X}. an_number(Z) -->

an_number(0, Z).

an_number(N, Z) --> [C],

{48 =< C, C =< 57, Z is 10^N * (C - 48)}. an_number(N, Z) -->

[C],

{48 =< C, C =< 57, X is 10^N * (C - 48), N1 is N+1}, an_number(N1, Y), {Z is X+Y}.

test1("1+2*2+3*3*3"). test2("0-123*1001-1001*321"). test3("6-3-2").

test4("6/3/2"). test5("123*2+123/3-287").

После отработки целевых утверждений для представленных в программе кода 6.4 тестов будут получены результаты:

? – test1(List), pars(List, Value).

… Value = 32

?– test2(List), pars(List, Value).

… Value = -444444

?– test3 (List), pars(List, Value).

… Value = 1

? – test4(List), pars(List, Value).

… Value = 1

? – test5(List), pars(List, Value).

Value = 0

3.Трансляция с ограниченного естественного языка в

ЯИП-1П

Следующий пример – преобразование фраз ограниченного естественного языка (ОЕЯ) в язык исчисления предикатов первого порядка (ЯИП-1П).

91

Данный пример позаимствован автором из книги У.Клоксина и К.Меллиша [4, с. 257 – 259].

Вкачестве ОЕЯ взято подмножество английского языка, так как

внём, в отличие от русского языка, «логические конструкции» выражаются более простыми средствами. Например, кванторы всеобщности и существования в английской и в русской фразах с одинаковым смыслом представляются так:

«Every man loves a woman»

«Для каждого мужчины существует некая женщина, которую он любит»

Следующий код демонстрирует решение данной задачи:

Код 6.5

:-op(100, xfy, &). :-op(150, xfy, '=>').

an_phrase(P) --> an_ng(X, P1, P), an_vg(X, P1).

an_ng(X, P1, P) -->

an_kv(X, P2, P1, P), an_noun(X, P3), an_aux(X, P3, P2).

an_ng(X, P, P) -->

an_name(X).

an_vg(X, P) -->

an_verb1(X, Y, Q), an_ng(Y, Q, P).

an_vg(X, P) -->

an_verb2(X, P).

an_aux(X, R1, (R1 & R2)) --> [that], an_vg(X, R2).

an_aux(_, R, R) --> [].

an_kv(X, Q, R, all(X, (Q => R))) --> [every]. an_kv(X, Q, R, exists(X, (Q & R))) --> [a].

92

an_name(X) -->

[X], {name_list(L), member(X, L)}.

an_noun(V, Z) -->

[X], {noun_list(L), member(X, L), Z=..[X, V]}.

an_verb1(V1, V2, Z) -->

[X], {verb1_list(L), member(X, L), Z=..[X, V1, V2]}.

an_verb2(V, Z) -->

[X], {verb2_list(L), member(X, L), Z=..[X, V]}.

name_list([Джон, Мери, Рекс, Чарли]). noun_list([man, woman, dog, cat]). verb1_list([loves, pursues]). verb2_list([lives, walks]).

test1([every, man, that, lives, loves, a, woman]). test2([every, dog, that, pursues, a, cat, loves, a, man, that,

loves, a, woman, that, walks]). test3([a, dog, pursues, Чарли]). test4([Рекс, loves, Джон]). test5([Мери, walks]).

Дадим пояснения некоторым предикатам данной программы: an_ng – анализ группы существительного,

an_vg – анализ группы глагола,

an_aux – анализ вспомогательного предложения (that ...), an_kv – анализ «квантора» (every, a),

an_name – анализ «имени» (наличие в списке «конкретных действующих лиц»),

an_noun – анализ существительного (наличие в списке «сущностей»),

an_verb1 – анализ «переходного» глагола (например, loves), an_verb2 – анализ «непереходного» глагола (например, lives).

93

После отработки целевых утверждений

?-test1(L), an_ph(Res, L, []). ?-test2(L), an_ph(Res, L, []). ?-test3(L), an_ph(Res, L, []). ?-test4(L), an_ph(Res, L, []). ?-test5(L), an_ph(Res, L, []).

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

структуры данных:

Res = all(X, man(X) & lives(X) =>

exists(Y, woman(Y) & loves(X, Y))).

Res = all(X, dog(X) & exists(Y, cat(Y) & pursues(X, Y)) => exists(Z, (man(Z) & exists(W, (woman(W) & walks(W)) & loves(Z, W))) & loves(X, Z))).

Res = exists(X, dog(X) & pursues(X, Чарли)). Res = loves(Рекс, Джон).

Res = walks(Мери).

94

Лекция 7

Программирование эффективных синтаксических анализаторов (продолжение)

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

типа. Для определённости будет представлена «учебная» модель такого языка – язык PL (Programming Language), – точнее, неболь-

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

1. Анализ активных и пассивных форм ОЕЯ

Речь будет идти о весьма распространенном в ограниченных естественных языках явлении – представлении одной и той же информации различными способами.

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

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

«Мой сосед купил дачу», «Дача куплена моим соседом»

соответствует глубинная структура

predicate(action(купить), agent(мой_сосед), object(дача)).

95

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

Рассмотрим пример очень простого фрагмента русского языка. В этом фрагменте в роли «агентов» и «объектов» некоторых

действий (например, любить, купить) выступают только личные местоимения (например, я, ты, меня, тебя, мною, тобою).

Входные цепочки типа

[он, любит, ее] или [она, любима, им]

должны быть преобразованы в одну глубинную структуру:

любить(он, она).

Отметим, что даже в таком ограниченном фрагменте языка может присутствовать довольно много различных форм местоимений и глаголов. Местоимения различаются по роду, числу, лицу и падежу. Глаголы могут быть в активном (действительном) и пассивном (страдательном) залоге, а также различаться по роду, числу, лицу. И хотя мы ограничимся рассмотрением только трёх падежей

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

Поэтому организуем специальные текстовые файлы с указанными данными и процедуру поиска нужной словоформы в том или ином файле непосредственно в ходе синтаксического анализа.

Использование словарей в виде текстовых файлов

Каждая запись файла-словаря будет представлять собой структуру Пролога вида

<Каноническая форма>: <Контекст>: <Список словоформ>.

Например:

купить: zalog(пассив):

[куплен, куплена, куплено, куплены]. любить: zalog(актив):

[люблю, любишь, любит, любим, любите, любят].

96

Ниже представлена программа такого анализатора (код 7.1), в текст которого включено определение предиката fid/4 – это процедура поиска в словаре (аббревиатура от find in dictionary).

Аргументы данного определения таковы:

1.X – исходная словоформа,

2.XC – каноническая форма слова,

3.K – контекст,

4.File – имя файла-словаря.

 

Код 7.1

%

Поиск словоформы в словаре.

:-op(200, xfy, ':').

 

fid(X, XC, K, File) :-

see(File), cycle(X, XC, K, R), seen, !, R = yes.

cycle(X, XC, K, R) :- repeat,

read(L), condition(X, XC, K, L, R), !.

condition(X, XC, K, XC:K:L, yes) :- member(X, L), !.

condition(_, _, _, L, no):-

L= end_of_file, !.

%Анализатор активных и пассивных форм. an_phrase(Y, zalog(актив)) -->

an_mest(X1, pad(именит)), an_glag(X2, zalog(актив)), an_mest(X3, pad(винит)), {Y=..[X2, X1, X3]}.

an_phrase(Y, zalog(пассив)) --> an_mest(X1, pad(именит)), an_glag(X2, zalog(пассив)), an_mest(X3, pad(творит)), {Y=..[X2, X3, X1]}.

97

an_mest(XC, K) -->

[X], {fid(X, XC, K, 'dic_mest')}.

an_glag(XC, K) --> [X], {fid(X, XC, K, 'dic_gl')}.

test1([ты, любишь, ее]). test2([она, любима, вами]). test3([оно, куплено, им]). test4([мы, купили, их]).

Содержимое файлов-словарей dic_mest и dic_gl

(коды 7.2 – 7.3):

Код 7.2

%

Словарь местоимений.

я: pad(именит): [я].

 

я: pad(винит): [меня].

 

я: pad(творит): [мной, мною].

 

ты: pad(именит):[ты].

 

ты: pad(винит): [тебя].

 

ты: pad(творит): [тобой, тобою].

 

он: pad(именит): [он].

 

он: pad(винит): [его].

 

он: pad(творит): [им].

 

она: pad(именит): [она].

 

она: pad(винит):[ее].

 

она: pad(творит): [ей, ею].

 

оно: pad(именит): [оно].

 

оно: pad(винит): [его].

 

оно: pad(творит): [им].

 

мы: pad(именит): [мы].

 

мы: pad(винит): [нас].

 

мы: pad(творит): [нами].

 

вы: pad(именит): [вы].

 

вы: pad(винит): [вас].

 

вы: pad(творит): [вами].

 

они: pad(именит):[они].

 

они: pad(винит): [их].

 

они: pad(творит): [ими].

 

98

 

 

Код 7.3

%

Словарь глаголов.

любить: zalog(актив):

 

[люблю, любишь, любит, любим, любите, любят]. любить: zalog(пассив):

[любим, любима, любимо, любимы]. купить: zalog(актив):

[купил, купила, купило, купили]. купить: zalog(пассив):

[куплен, куплена, куплено, куплены].

После отработки целевых утверждений

?-test1(L),

an_phrase(Res, K, L, []).

?-test2(L),

an_phrase(Res, K, L, []).

?-test3(L),

an_phrase(Res, K, L, []).

?-test4(L),

an_phrase(Res, K, L, []).

будут возвращены следующие значения переменной Res и K:

Res = любить(ты, она) Res = любить(вы, она) Res = купить(он, оно) Res = купить(мы, они)

K = zalog(актив) K = zalog(пассив) K = zalog(пассив) K = zalog(актив)

2. Морфологический анализ слов ОЕЯ

Рассмотрим пример, который относится к так называемому морфологическому анализу (разбору слов русского языка) – выделению приставок (префиксов), суффиксов, окончаний и т.д.

Для простоты рассмотрим лишь задачу отделения окончания слова от его «основы», то есть от оставшейся части слова без окончания. Например, разбор прилагательных красивый и прекрасная должен дать такие структуры:

morf(osnova(красив), okonch(pril: pad(именит): rod(муж), ый))

morf(osnova(прекрасн), okonch(pril: pad(именит): rod('жен'), ая))

Всевозможные окончания прилагательных будем хранить в словаре (файле dic_ocon). Фрагмент словаря представлен кодом 7.4.

99

 

Код 7.4

%

Словарь окончаний.

_: (pril: pad(именит): rod(муж)):

[ый, ий].

_: (pril: pad(именит): rod(жен)): [ая, яя]. _: (pril: pad(именит): rod(сред)): [ое, ее].

_: (pril: pad(именит): chislo(множ)): [ые, ие]. _: (pril: pad(родит): rod(муж)): [ого, его].

_: (pril: pad(родит): rod(жен)): [ой, ей].

_: (pril: pad(родит): rod(сред)): [ого, его]. _: (pril: pad(родит): chislo(множ)): [ых, их].

Здесь присутствуют лишь данные об окончаниях прилагательных в двух падежах – именительном и родительном. Анонимная переменная в левой части структуры говорит о том, что канонической формы у окончаний нет.

Программа указанного морфологического анализа (код 7.5):

Код 7.5

:-op(200, xfy, ':').

an_morf(Result, InpL, RestL):-

reverse(InpL, L),

an_morf1(Result, L, RestL).

an_morf1(morf(Osn, Okon)) -->

an_okon(Okon), an_osn(Osn, [], C).

an_okon(okonch(K, X)) -->

% Анализ окончания.

[B1, B2, B3],

 

{name(X, [B3, B2, B1]),

fid(X, _, K, 'dic_okon')}.

an_okon(okonch(K, X)) -->

 

[B1, B2],

 

{name(X, [B2, B1]), fid(X, _, K, 'dic_okon')}. an_okon(okonch(K, X)) -->

[B1],

{name(X, [B1]), fid(X, _, K, 'dic_okon')}. an_okon(okonch(void)) --> [].

100

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]