Чтобы ответить на дополнительный вопрос, который был добавлен позже: вы можете передавать информацию, добавляя дополнительные аргументы, но вам нужно описать последовательность предложений.Пример phrase(s, [peter, is, father, of, guido]), phrase(s, [he, is, a, male])
должен быть успешным, то, что не должно быть успешным, - это произносить два предложения друг за другом phrase(ss, [peter, is, father, of, guido, '.', he, is, a, male,'.'])
(Или это может быть успешным, оставляя «он» в качестве ссылки на кого-то, кого мы не знаем. Все зависит от того, насколько мы строгиес контекстом.).
Чтобы сделать это правильно, нам нужно прыгнуть довольно много обручей.Сначала нам нужно добавить информацию об анализе в правила DCG.Например, np(np([A,O],object)) --> %...
будет анализировать статью, за которой следует объект, в структуру np([A,O],object)
.Давайте разберем ['a', 'male']
и [guido]
с ним:
?- phrase(np(NP), [a, male]).
NP = np([article(a), object(male, male)], object) ;
false.
?- phrase(np(NP), [guido]).
NP = np([name(guido, male)], name) ;
false.
Первый аргумент np
- это список, потому что другие правила np имеют только для компонента.Обратите внимание, что мы добавили пол в качестве атрибута к name
и object
.На других языках, например на французском, статья также имеет пол, который должен согласовываться с объектом, но на английском языке мы можем оставить это в стороне.Более сложные реализации также будут учитывать, если объект находится в единственном или множественном числе (то же самое относится и к различным модам глагола).
Для глаголов нам нужно различать, сколько фраз существительного им нужно.Это делается с помощью проверок is_transitive/1
, is_intransitive/1
и is_bitransitive/1
.
Найти хорошее решение для наглядных местоимений сложно: местоимению не нужно ссылаться на предыдущий предмет, например, в «Гейле женат на Петре. Он старше ее».Даже не нужно ссылаться на последнее предложение, например, «Питер там, где он хочет быть».Это означает, что: а) вы должны заранее решить, какие случаи вы действительно хотите охватить, и б) лучше всего принимать эти решения во втором прогоне анализа, когда у вас есть полная структурированная информация.Это отражает лингвистическое различие между синтаксическими, семантическими и прагматическими рассуждениями , где я бы классифицировал проблему, которую вы хотели бы решить, как прагматическую, которая зависит от двух других шагов.
Мое решение здесьпросто включает конкретное решение, которое вы хотели принять, в один анализ, за счет читабельности правила ss
DCG: мы добавляем дополнительный аргумент, который собирает уже проанализированные предложения, так называемый аккумулятор.Когда мы начинаем синтаксический анализ, история пуста, что отражается правилом ss(S) --> ss(S,[]).
.Для фактических правил нам нужно различать, начинается ли текущее предложение с демонстративного местоимения или нет.В первом случае нам нужно решить эту проблему, что мы делаем здесь, посмотрев на возможные фразы существительного в предыдущем предложении, которые согласуются по полу.Имея этот механизм, мы можем разобрать предложение [peter, is, a father, '.', he, is a father,'.']
:
?- phrase(ss(Tree), [peter,is,a,father,'.', he, is, a, father, '.']).
Tree = [s(np([name(peter, male)], name), vp([verb(is), np([article(a), object(father, male)], object)])), s(np([pronoun(he, male)], dpronoun), vp([verb(is), np([article(a), object(..., ...)], object)]))] ;
, но не можем разобрать [peter,is,a,father,'.', she, is, a, father, '.']
:
?- phrase(ss(Tree), [peter,is,a,father,'.', she, is, a, father, '.']).
false.
В правильном семантическом / прагматическом анализе мыобогатит местоименную фразу фактической именованной именной фразой, но это будет сделано как переписывание исходного дерева разбора.Вот код для этого:
%%%% utility predicates
% gender_of(X,Y) is true if X is the gender of the syntax tree node Y
gender_of(X,name(_,X)).
gender_of(X,pronoun(_,X)).
gender_of(X,object(_,X)).
gender_of(G,np([X],_)) :-
gender_of(G,X).
gender_of(G,np([_,X],_)) :-
gender_of(G,X).
% nps_of(X,Y) is true if X is the list of nps occurring in the syntax tree node Y
nps_of([],vp([_])).
nps_of([NP],vp([_,NP])).
nps_of([NP|Rest],s(NP,VP)) :-
nps_of(Rest, VP).
% nountype_of(X,Y) is true if X is the type of the np node Y
nountype_of(X, np(_,X)).
% is_intransitive(X) is true if the verb X does not require an object phrase
is_intransitive(is).
is_intransitive(walk).
% is_transitive(X) is true if the verb X requires an object phrase
is_transitive(is).
% is_bitransitive(X) is true if the verb X requires two object phrases
is_bitransitive(is).
%%%% DCG rules
% name are distinct from objects because they do not require articles
name(name(peter,male)) --> [peter].
name(name(isabel,female)) --> [isabel].
name(name(guido,male)) --> [guido].
name(name(claudia,female)) --> [claudia].
% nouns that require an article
object(object(mother,female)) --> [mother].
object(object(father,male)) --> [father].
object(object(male,male)) --> [male].
object(object(female,female)) --> [female].
% verbs
verb(verb(is)) --> [is].
verb(verb(walk)) --> [walks].
% pronouns
pronoun(pronoun(he,male)) --> [he].
pronoun(pronoun(she,female)) --> [she].
% articles
article(article(a)) -->
[a].
article(article(the)) -->
[the].
% noun phrases
np(np([A,O],object)) -->
article(A),
object(O).
np(np([N],name)) -->
name(N).
np(np([PN], dpronoun)) -->
pronoun(PN).
% verb phrases
vp(vp([V,NP])) -->
verb(V),
{ V = verb(Name), is_transitive(Name) },
np(NP).
vp(vp([V])) -->
verb(V),
{ V = verb(Name), is_intransitive(Name) }.
end -->
['.'].
% a single sentence
s(s(NP,VP)) -->
np(NP),
vp(VP),
end.
% a list of sentences, with accumulator
ss([],_Acc) -->
[].
ss([S|Sentences],[]) -->
s(S),
ss(Sentences, [S]).
ss([S|Sentences], [LastS | Acc]) -->
{ S = s(np([Pronoun], dpronoun),_) },
s(S),
{ gender_of(G, Pronoun), nps_of(LastNPS, LastS), member(LNP, LastNPS), gender_of(G,LNP) },
ss(Sentences, [S, LastS | Acc]).
ss([S|Sentences], [LastS | Acc]) -->
{ S = s(NP,_), nountype_of(NT,NP), dif(NT,dpronoun) },
s(S),
ss(Sentences, [S, LastS | Acc]).
% wrapper of ss with empty accumulator
ss(S) -->
ss(S,[]).