<div class="notebook open-fullscreen"> <div class="nb-cell markdown" name="md1"> # Materialien zu Kapitel 2 (Teil 3: Grammar Engineering) ## Die Syntax-Regeln - Die DCGs werden angereichert mit Attribut-Wert-Paaren, die z.B. Kongruenzphänomene steuern. - =combine/2= verbindet die Syntax mit der Semantik (siehe semRulesLambda.pl) - Koordination wird über das Attribut =coord= gesteuert, um Linksrekursion zu vermeiden: </div> <div class="nb-cell program" data-background="true" name="p5"> % Auszug aus englishGrammar.pl % T -> S t([sem:T])--> s([coord:no,sem:S]), {combine(t:T,[s:S])}. t([sem:T])--> s([coord:yes,sem:S]), {combine(t:T,[s:S])}. % S -> NP VP s([coord:no,sem:Sem])--> np([coord:_,num:Num,gap:[],sem:NP]), vp([coord:_,inf:fin,num:Num,gap:[],sem:VP]), {combine(s:Sem,[np:NP,vp:VP])}. % NP -> D NP np([coord:no,num:sg,gap:[],sem:NP])--> det([mood:decl,type:_,sem:Det]), n([coord:_,sem:N]), {combine(np:NP,[det:Det,n:N])}. % NP -> PN np([coord:no,num:sg,gap:[],sem:NP])--> pn([sem:PN]), {combine(np:NP,[pn:PN])}. % NP -> NP and NP, % das Attribut 'coord' steuert die Vermeidung von Linksrekursion np([coord:yes,num:pl,gap:[],sem:NP])--> np([coord:no,num:sg,gap:[],sem:NP1]), coord([type:conj,sem:C]), np([coord:_,num:_,gap:[],sem:NP2]), {combine(np:NP,[np:NP1,coord:C,np:NP2])}. % NP -> NP or NP np([coord:yes,num:sg,gap:[],sem:NP])--> np([coord:no,num:sg,gap:[],sem:NP1]), coord([type:disj,sem:C]), np([coord:_,num:sg,gap:[],sem:NP2]), {combine(np:NP,[np:NP1,coord:C,np:NP2])}. % N -> Noun n([coord:no,sem:N])--> noun([sem:Noun]), {combine(n:N,[noun:Noun])}. % VP -> IV vp([coord:no,inf:Inf,num:Num,gap:[],sem:VP])--> iv([inf:Inf,num:Num,sem:IV]), {combine(vp:VP,[iv:IV])}. % VP -> TV NP vp([coord:no,inf:I,num:Num,gap:G,sem:VP])--> tv([inf:I,num:Num,sem:TV]), np([coord:_,num:_,gap:G,sem:NP]), {combine(vp:VP,[tv:TV,np:NP])}. </div> <div class="nb-cell markdown" name="md2"> Terminalregeln - =lexEntry/2= greift auf `englishLexicon.pl` zu. - =semLex/2= greift auf `semLexLambda.pl` zu. </div> <div class="nb-cell program" data-background="true" name="p2"> % Lexical Rules iv([inf:Inf,num:Num,sem:Sem])--> {lexEntry(iv,[symbol:Sym,syntax:Word,inf:Inf,num:Num])}, Word, {semLex(iv,[symbol:Sym,sem:Sem])}. tv([inf:Inf,num:Num,sem:Sem])--> {lexEntry(tv,[symbol:Sym,syntax:Word,inf:Inf,num:Num])}, Word, {semLex(tv,[symbol:Sym,sem:Sem])}. det([mood:M,type:Type,sem:Det])--> {lexEntry(det,[syntax:Word,mood:M,type:Type])}, Word, {semLex(det,[type:Type,sem:Det])}. pn([sem:Sem])--> {lexEntry(pn,[symbol:Sym,syntax:Word])}, Word, {semLex(pn,[symbol:Sym,sem:Sem])}. noun([sem:Sem])--> {lexEntry(noun,[symbol:Sym,syntax:Word])}, Word, {semLex(noun,[symbol:Sym,sem:Sem])}. </div> <div class="nb-cell markdown" name="md3"> ## Das Lexikon Lexikalische Einträge haben die Form lexEntry(Cat,Feature). =Cat= denotiert die syntaktische Kategorie, =Feature= ist eine Liste von Attribut-Wertpaaren. </div> <div class="nb-cell program" data-background="true" name="p6"> % Auszug aus englishLexicon.pl % Determiners lexEntry(det,[syntax:[every],mood:decl,type:uni]). lexEntry(det,[syntax:[a],mood:decl,type:indef]). % Nouns lexEntry(noun,[symbol:footmassage,syntax:[foot,massage]]). lexEntry(noun,[symbol:customer,syntax:[customer]]). lexEntry(noun,[symbol:robber,syntax:[robber]]). lexEntry(noun,[symbol:boxer,syntax:[boxer]]). % Proper Names lexEntry(pn,[symbol:yolanda,syntax:[yolanda]]). lexEntry(pn,[symbol:vincent,syntax:[vincent]]). lexEntry(pn,[symbol:butch,syntax:[butch]]). lexEntry(pn,[symbol:mia,syntax:[mia]]). % Intransitive Verbs lexEntry(iv,[symbol:smoke,syntax:[smokes],inf:fin,num:sg]). lexEntry(iv,[symbol:smoke,syntax:[smoke],inf:fin,num:pl]). lexEntry(iv,[symbol:snort,syntax:[snorts],inf:fin,num:sg]). lexEntry(iv,[symbol:snort,syntax:[snort],inf:fin,num:pl]). lexEntry(iv,[symbol:dance,syntax:[dances],inf:fin,num:sg]). lexEntry(iv,[symbol:dance,syntax:[dance],inf:fin,num:pl]). % Transitive Verbs lexEntry(tv,[symbol:love,syntax:[loves],inf:fin,num:sg]). lexEntry(tv,[symbol:love,syntax:[love],inf:fin,num:pl]). lexEntry(tv,[symbol:know,syntax:[knows],inf:fin,num:sg]). lexEntry(tv,[symbol:know,syntax:[know],inf:fin,num:pl]). % Coordinations lexEntry(coord,[syntax:[and],type:conj]). lexEntry(coord,[syntax:[or],type:disj]). </div> <div class="nb-cell markdown" name="md4"> ## Das Semantische Lexikon =semLex/2= gibt die semantische Repräsentation im Lambda-Kalkül von lexikalischen Einträgen. </div> <div class="nb-cell program" data-background="true" name="p7"> % Auszug aus semLexLambda.pl semLex(det,M):- M = [type:uni, sem:lam(U,lam(V,all(X,imp(app(U,X),app(V,X)))))]. semLex(det,M):- M = [type:indef, sem:lam(P,lam(Q,some(X,and(app(P,X),app(Q,X)))))]. semLex(pn,M):- M = [symbol:Sym, sem:lam(P,app(P,Sym))]. semLex(noun,M):- M = [symbol:Sym, sem:lam(X,Formula)], compose(Formula,Sym,[X]). semLex(iv,M):- M = [symbol:Sym, sem:lam(X,Formula)], compose(Formula,Sym,[X]). semLex(tv,M):- M = [symbol:Sym, sem:lam(K,lam(Y,app(K,lam(X,Formula))))], compose(Formula,Sym,[Y,X]). semLex(coord,M):- M = [type:conj, sem:lam(X,lam(Y,lam(P,and(app(X,P),app(Y,P)))))]; M = [type:disj, sem:lam(X,lam(Y,lam(P,or(app(X,P),app(Y,P)))))]. </div> <div class="nb-cell markdown" name="md5"> ## Die semantischen Regeln Die =combine/2=-Regeln haben zwei Formen: - In binären Zweigen appliziere den Funktor auf das Argument mit =app/2= - In unären Zweigen wird die Repräsentation des Tochterknotens zum Mutterknoten weitergereicht </div> <div class="nb-cell program" data-background="true" name="p8"> % Auszug aus semRulesLambda.pl combine(t:Converted,[s:Sem]):- betaConvert(Sem,Converted). combine(s:app(A,B),[np:A,vp:B]). combine(np:app(app(B,A),C),[np:A,coord:B,np:C]). combine(np:app(A,B),[det:A,n:B]). combine(np:A,[pn:A]). combine(n:app(app(B,A),C),[n:A,coord:B,n:C]). combine(n:A,[noun:A]). combine(vp:A,[iv:A]). combine(vp:app(A,B),[tv:A,np:B]). </div> <div class="nb-cell markdown" name="md6"> # Lambda Das Kernprädikat =lambda/2= (bzw. =lambda/0=) berechnet für beliebige Inputsätze die semantischen Repräsentationen. Ähnlich wie in Kapitel 1 wird uns eine Testsuite zur Verfügung gestellt, mit der wir eine Reihe von Sätzen der Form sentence(Sentence,Readings) durchtesten können. Die zweite Argumentstelle gibt an, wie viele Lesarten der jeweilige Satz hat. </div> <div class="nb-cell program" data-background="true" name="p9"> % Auszug aus lambda.pl lambda(Sentence,Sems):- setof(Sem,t([sem:Sem],Sentence,[]),Sems). lambda:- readLine(Sentence), lambda(Sentence,Sems), printRepresentations(Sems). lambdaTestSuite:- nl, write('>>>>> LAMBDA ON SENTENCE TEST SUITE <<<<< '), nl, sentence(Sentence,_), nl, write('Sentence: '), write(Sentence), lambda(Sentence,Formulas), printRepresentations(Formulas), fail. lambdaTestSuite. /*======================================================================== Info ========================================================================*/ info:- format('~n> ------------------------------------------------------------------ <',[]), format('~n> lambda.pl, by Patrick Blackburn and Johan Bos <',[]), format('~n> <',[]), format('~n> ?- lambda. - parse a typed-in sentence <',[]), format('~n> ?- lambda(S,F). - parse a sentence and return formula <',[]), format('~n> ?- lambdaTestSuite. - run the test suite <',[]), format('~n> ?- info. - shows this information <',[]), format('~n> ------------------------------------------------------------------ <',[]), format('~n~n',[]). </div> <div class="nb-cell query" name="q1"> info. </div> <div class="nb-cell program" data-background="true" name="p11"> % Auszug aus sentenceTestSuite.pl sentence([mia,dances],1). sentence([mia,or,vincent,dances],1). sentence([every,customer,smokes],1). sentence([a,customer,smokes],1). sentence([mia,or,a,man,dances],1). sentence([every,woman,or,a,man,dances],2). sentence([every,man,or,woman,dances],1). sentence([mia,knows,a,man],1). sentence([vincent,knows,every,woman,or,a,man],2). sentence([vincent,knows,every,man,or,woman],1). </div> <div class="nb-cell program" data-background="true" data-singleline="true" name="p1"> % Auszug aus comsemPredicates.pl compose(Term,Symbol,ArgList):- Term =.. [Symbol|ArgList]. memberList(X,[X|_]). memberList(X,[_|Tail]):- memberList(X,Tail). printRepresentations(Readings):- printRep(Readings,0). printRep([],_):- nl. printRep([Reading|OtherReadings],M):- N is M + 1, nl, write(N), tab(1), \+ \+ (numbervars(Reading,0,_), print(Reading)), printRep(OtherReadings,N). </div> <div class="nb-cell program" data-background="true" data-singleline="true" name="p3"> % Auszug aus betaConversion.pl /*======================================================================== Beta-Conversion (introducing stack) ========================================================================*/ % ?- betaConvert(app(lam(U,app(U,mia)),lam(X,smoke(X))),Converted). % introduce empty stack betaConvert(X,Y):- betaConvert(X,Y,[]). /*======================================================================== Beta-Conversion (core stuff) ========================================================================*/ % expression is a variable => do nothing betaConvert(X,Y,[]):- var(X), !, Y=X. % expression is application => push argument to stack betaConvert(Expression,Result,Stack):- nonvar(Expression), Expression = app(Functor,Argument), %% To suppress alpha-conversion: alphaConvert(Functor,Converted), %% comment-out this line % Functor=Converted, %% comment-in this line betaConvert(Converted,Result,[Argument|Stack]), !. % expression is abstraction + stack is not empty => pop argument from stack betaConvert(Expression,Result,[X|Stack]):- nonvar(Expression), Expression = lam(X,Formula), betaConvert(Formula,Result,Stack), !. % other expression => break down complex expression betaConvert(Formula,Result,[]):- nonvar(Formula), !, compose(Formula,Functor,Formulas), betaConvertList(Formulas,ResultFormulas), compose(Result,Functor,ResultFormulas). betaConvert(Exp,app(Exp,Y),[X]):- %% Impossible to perform application. betaConvert(X,Y). /*======================================================================== Beta-Convert a list ========================================================================*/ betaConvertList([],[]). betaConvertList([Formula|Others],[Result|ResultOthers]):- betaConvert(Formula,Result), betaConvertList(Others,ResultOthers). </div> <div class="nb-cell program" data-background="true" data-singleline="true" name="p4"> % Auszug aus alphaConversion.pl /*======================================================================== Alpha Conversion (introducing substitutions) ========================================================================*/ alphaConvert(F1,F2):- alphaConvert(F1,[],[]-_,F2). /*======================================================================== Alpha Conversion ========================================================================*/ alphaConvert(X,Sub,Free1-Free2,Y):- var(X), ( memberList(sub(Z,Y),Sub), X==Z, !, Free2=Free1 ; Y=X, Free2=[X|Free1] ). alphaConvert(Expression,Sub,Free1-Free2,some(Y,F2)):- nonvar(Expression), Expression = some(X,F1), alphaConvert(F1,[sub(X,Y)|Sub],Free1-Free2,F2). alphaConvert(Expression,Sub,Free1-Free2,all(Y,F2)):- nonvar(Expression), Expression = all(X,F1), alphaConvert(F1,[sub(X,Y)|Sub],Free1-Free2,F2). alphaConvert(Expression,Sub,Free1-Free2,lam(Y,F2)):- nonvar(Expression), Expression = lam(X,F1), alphaConvert(F1,[sub(X,Y)|Sub],Free1-Free2,F2). alphaConvert(Expression,Sub,Free1-Free3,que(Y,F3,F4)):- nonvar(Expression), Expression = que(X,F1,F2), alphaConvert(F1,[sub(X,Y)|Sub],Free1-Free2,F3), alphaConvert(F2,[sub(X,Y)|Sub],Free2-Free3,F4). alphaConvert(F1,Sub,Free1-Free2,F2):- nonvar(F1), \+ F1 = some(_,_), \+ F1 = all(_,_), \+ F1 = lam(_,_), \+ F1 = que(_,_,_), compose(F1,Symbol,Args1), alphaConvertList(Args1,Sub,Free1-Free2,Args2), compose(F2,Symbol,Args2). /*======================================================================== Alpha Conversion (listwise) ========================================================================*/ alphaConvertList([],_,Free-Free,[]). alphaConvertList([X|L1],Sub,Free1-Free3,[Y|L2]):- alphaConvert(X,Sub,Free1-Free2,Y), alphaConvertList(L1,Sub,Free2-Free3,L2). /*======================================================================== Alphabetic Variants ========================================================================*/ alphabeticVariants(Term1,Term2):- alphaConvert(Term1,[],[]-Free1,Term3), alphaConvert(Term2,[],[]-Free2,Term4), Free1==Free2, numbervars(Free1,0,N), numbervars(Term3,N,M), numbervars(Term4,N,M), Term3=Term4. </div> <div class="nb-cell program" data-background="true" data-singleline="true" name="p10"> % swish helper :-style_check(-discontiguous). :-style_check(-singleton). :- use_rendering(mathjax). </div> </div>