从Prolog DCG创建列表

时间:2019-05-19 11:35:17

标签: list prolog dcg

我不知道如何创建一个列表,其中包含使用已定义的DCG用来构成句子的元素。

假设我们有以下DCG:

father --> [Peter].
mother --> [Isabel].

child --> [Guido].
child --> [Claudia].

verb --> [is].
relation --> [father, of].
relation --> [mother, of].

pronoun --> [he].
pronoun --> [she].

adjective --> [a, male].
adjective --> [a, female].

s --> father, verb, relation, child.
s --> mother, verb, relation, child.
s --> pronoun, verb, adjective.

可以按以下方式查询句子: phrase(s, [peter, is, father, of, guido]), phrase(s, [he, is, a, male]).返回true

如何在执行以下语句时创建并维护此已执行语句的元素列表,以便获得false(因为Peter是男性,请注意she而不是{{ 1}}):

he

此问题使用与here相同的示例。

2 个答案:

答案 0 :(得分:0)

DCG的正确接口是通过phrase/2phrase/3的简化版本):

?- phrase(s, X).
X = [_8304, is, father, of, _8328] ;
X = [_8304, is, father, of, _8328] ;
X = [_8304, is, mother, of, _8328] ;
% etc

_8404变量来自诸如father --> [Peter].之类的规则,因为其中的Peter还有一个变量(变量以_或大写字母开头。您可以解决此问题通过将原子转义为'Peter'-另请参阅您问的另一个问题)。

短语的名字是DCG规则,第二个参数是列表。当使用特定列表作为第二个参数时,答案替换为空,并且Prolog仅报告它可以派生该列表。在我的示例中,我使用了变量X,并获得了可能的替代变量,可以将其导出。

可以将约束添加为大括号内的目标:

dupnum(X) --> 
   { member(X, [0,1,2,3,4,5,6,7,8,9]) },
   [X,X].

导致

?- phrase(dupnum(X), Y).
X = 0,
Y = [0, 0] ;
X = 1,
Y = [1, 1] ;
% etc

该示例还显示,DCG生产中可以包含可用于传播解析树或某些常规解析上下文的参数。

答案 1 :(得分:0)

要解决稍后添加的其他问题:您可以通过添加其他参数来传递信息,但是您需要描述句子的顺序。示例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规则仅具有分量。请注意,我们将性别作为属性添加到nameobject。在其他语言(例如法语)中,文章的性别也需要与对象一致,但在英语中,我们可以将其保留。如果宾语是单数或复数,也将考虑更复杂的实现(对于动词的不同模式也是如此)。

对于动词,我们需要区分它们需要多少个宾语名词短语。这通过检查is_transitive/1is_intransitive/1is_bitransitive/1完成。

要为指示代词找到一个好的解决方案很困难:代词不需要引用先前的主题,例如在“盖伊尔嫁给彼得。他比彼得大”中。甚至根本不需要引用最后一句话,例如在“彼得就是他想去的地方”中。这意味着a)您应该事先确定您实际要涵盖的情况,b)拥有完整的结构化信息后,最好在第二次分析中做出这些决定。这反映了syntactic, semantic and pragmatic reasoning之间的语言区别,我将您要解决的问题归为务实的,这取决于其他两个步骤。

在这里,我的解决方案只是将您要做出的特定决定合并到单个解析过程中,但要以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,[]).