% Discourse 2009

% Groep 1 & 2 code:
:- [interpret2020].

go :-
	retractall(tel(_)), assert(tel(1)),	
	%blank slate
	DRS = drs([], []),
	S = [
		['in', 'het', 'midden', 'van', 'het', 'hartje', 'van', 'het', 'binnenste', 
			'van', 'het', 'muiskleurig', 'gebergte', 'woonde', 'de', 'weerwolf'],
		['hij', 'was', 'groot', 'en', 'verschrikkelijk'],
		['zijn', 'ogen', 'sproeiden', 'vuur', 'en', 'zijn', 'tong', 'had', 'karteltjes']
	],
	analyse(S, DRS, NewDRS),
	%S1 = ['iedere', 'avond', 'om', 'zes', 'uur', 'stiet', 'hij', 'een', 'gebrul', 'uit', 'waarvan', 'het', 'hele', 'muiskleurige', 'gebergte', 'sidderde'], interpret(S1, M1, NewDRS),
	%this sentence is not interpreted correctly yet, so here is a hardcoded version
        M1 = [  lex(hij, [], [find(33), pronoun(1), male(33), singular(1), animate(33)], 1),
                lex(had, [1, 3], [verb(2), pastTense(2), eat(1), eat(3), singular(1), noun(1), before(1), noun(3), after(3)], 2),
                lex(lange, [4], [adj(3), eat(4), noun(4), next(4), same_features(3, 4)], 3),
                lex(witte, [5], [adj(4), eat(5), noun(5), next(5), same_features(4, 5)], 4),
                lex(scherpe, [6], [adj(5), eat(6), noun(6), next(6), same_features(5, 6)], 5),
                lex(tanden, [], [noun(6), plural(6), inanimate(6)], 6),
                lex(en, [2, 18], [conn(7), eat(2), eat(18)], 7),
                lex(iedere, [9, 13], [univ(8), eat(9), noun(9), next(9), singular(9), same_features(8, 9), verb(13), eat(13)], 8),
                lex(avond, [], [noun(9), inanimate(9), singular(9), male(9)], 9),
%               lex(om, [8, 11], [prep(10), eat(8), before(8), noun(8), eat(11), noun(11), after(11)], 10),
%               lex(zes, [12], [det(11), eat(12), noun(12), next(12), same_features(11, 12)], 11),
%               lex(uur, [], [noun(12), neuter(12), inanimate(12)], 12),
                lex(stiet, [14, 15, 17], [verb(13), pastTense(13), eat(14), eat(15), eat(17), singular(14), animate(14), noun(15), after(15), particle(17)], 13),
                lex(hij, [], [find(33), pronoun(14), male(33), singular(14), animate(33)], 14),
                lex(een, [16], [det(15), bind(15), eat(16), next(16), noun(16), singular(16), same_features(15, 16)], 15),
                lex(gebrul, [], [noun(16), singular(16), neuter(16), inanimate(16)], 16),
                lex(uit, [], [particle(17)], 17) ,
                lex(waarvan, [16, 23], [prep(18), eat(10), eat(23), prep(10), verb(23)], 18),
                lex(het, [20], [det(19), find(11), eat(20), next(20), neuter(20), same_features(19, 20)], 19),
                lex(hele, [21], [adj(20), eat(21), noun(21), next(21), same_features(20, 21)], 20),
                lex(muiskleurige, [22], [adj(21), noun(22), next(22), same_features(21, 22), eat(22)], 21) ,
                lex(gebergte, [], [noun(22), neuter(22), singular(22)], 22),
                lex(sidderde, [19], [verb(23), pastTense(23), singular(19), before(19), noun(19), eat(19)], 23)],
	docontext(M1, M1, NewDRS, NNewDRS),
	analyse([ ['dat', 'is', 'de', 'weerwolf'] ], NNewDRS, _NNNewDRS).

go(S) :-
	retractall(tel(_)), assert(tel(1)),	
	%blank slate
	DRS = drs([], []),
	analyse([S], DRS, _).


gokat :-
	retractall(tel(_)), assert(tel(1)),	
	%blank slate
	DRS = drs([], []),
	S = [ [ik,zie,een,rode,kat], [ik,zie,een,blauwe,mat], [de,kat,zit,op,de,mat] ],
	analyse(S, DRS, _).  

analyse([], DRS, DRS).
analyse([Sentence | Rest], DRS, Result) :-
        interpret(Sentence, Meaning, DRS),
        writeln('Interpretation: '), writelist(Meaning), nl,
        %generatie check?
        docontext(Meaning, Meaning, DRS, drs(Ref, Cond)),
        writeln('Sentence: '), writeln(Sentence), nl,
        writeln('Meaning: '), writelist(Meaning), nl,
        writeln('Context: '),
        % 'pretty-print' DRS
        writeln(Ref), writeln('--------------'), writelist(Cond), nl,
        analyse(Rest, drs(Ref, Cond), Result).

writelist([]).
writelist([Head | Tail]) :-
        writeln(Head),
        writelist(Tail).


% Groep 3: context model
gocontext :-
	retractall(tel(_)),
	assert(tel(1)),
	DRS = drs([], []),
	Meaning = [lex(hij, [], [find(1), pronoun(1), male(1), singular(1), animate(1)], 1),
		lex(had, [1, 3], [verb(2), pastTense(2), eat(1), eat(3), singular(1), noun(1), before(1), noun(3), after(3)], 2),
		lex(lange, [4], [adj(3), eat(4), noun(4), next(4), same_features(3, 4)], 3),
		lex(witte, [5], [adj(4), eat(5), noun(5), next(5), same_features(4, 5)], 4),
		lex(scherpe, [6], [adj(5), eat(6), noun(6), next(6), same_features(5, 6)], 5),
		lex(tanden, [], [noun(6), plural(6), inanimate(6)], 6),
		lex(en, [2, 18], [conn(7), eat(2), eat(18)], 7),
		lex(iedere, [9, 13], [univ(8), eat(9), noun(9), next(9), singular(9), same_features(8, 9), verb(13), eat(13)], 8),
		lex(avond, [], [noun(9), inanimate(9), singular(9), male(9)], 9),
%		lex(om, [8, 11], [prep(10), eat(8), before(8), noun(8), eat(11), noun(11), after(11)], 10),
%		lex(zes, [12], [det(11), eat(12), noun(12), next(12), same_features(11, 12)], 11),
%		lex(uur, [], [noun(12), neuter(12), inanimate(12)], 12),
		lex(stiet, [14, 15, 17], [verb(13), pastTense(13), eat(14), eat(15), eat(17), singular(14), animate(14), noun(15), after(15), particle(17)], 13),
		lex(hij, [], [find(14), noun(14), male(14), singular(14), animate(14)], 14),
		lex(een, [16], [det(15), bind(15), eat(16), next(16), noun(16), singular(16), same_features(15, 16)], 15),
		lex(gebrul, [], [noun(16), singular(16), neuter(16), inanimate(16)], 16),
		lex(uit, [], [particle(17)], 17) ,
		lex(waarvan, [16, 23], [prep(18), eat(10), eat(23), prep(10), verb(23)], 18),
		lex(het, [20], [det(19), find(19), eat(20), next(20), neuter(20), same_features(19, 20)], 19),
		lex(hele, [21], [adj(20), eat(21), noun(21), next(21), same_features(20, 21)], 20),
		lex(muiskleurige, [22], [adj(21), noun(22), next(22), same_features(21, 22), eat(22)], 21) ,
		lex(gebergte, [], [noun(22), neuter(22), singular(22)], 22),
		lex(sidderde, [19], [verb(23), pastTense(23), singular(19), before(19), noun(19), eat(19)], 23)],
	/*
	Meaning = [   lex(in, [14, 4], [prep(1), eat(14), eat(4), verb(14), prep(4), 
		   after(4)], 1),
		   lex(het, [3], [det(2), find(2), eat(3), next(3), neuter(3), same_features(2, 3)], 2),
		   lex(midden, [], [noun(3), neuter(3)], 3),   
		   lex(van, [2, 7], [prep(4), eat(2), eat(7), noun(2), prep(7), before(2), after(7)], 4)    ,
		   lex(het, [6], [det(5), find(5), eat(6), next(6), neuter(6),    
		   same_features(5, 6)], 5)    ,
		   lex(hartje, [], [noun(6), neuter(6)], 6)  ,
		   lex(van, [5, 10], [prep(7), eat(5), eat(10), noun(5), prep(10),
		   before(5), after(10)], 7)   ,
		   lex(het, [9], [det(8), find(8), eat(9), next(9), neuter(9),    
		   same_features(8, 9)], 8)    ,
		   lex(binnenste, [], [noun(9), neuter(9)], 9)      ,
		   lex(van, [8, 11], [prep(10), eat(8), eat(11), noun(8), noun(11),      
		   before(8), after(11)], 10)  ,
		   lex(het, [12], [det(11), find(11), eat(12), next(12), neuter(12),     
		   same_features(11, 12)], 11) ,
		   lex(muiskleurig, [13], [adj(12), eat(13), noun(13), next(13),  
		   same_features(12, 13)], 12) ,
		   lex(gebergte, [], [noun(13), neuter(13), singular(13)], 13)    ,
		   lex(woonde, [15], [verb(14), singular(14), past(14), eat(15),  
		   noun(15), animate(15)], 14) ,
		   lex(de, [16], [det(15), find(15), eat(16), noun(16), next(16), 
		   male(16), same_features(15, 16)], 15)     ,
		   lex(weerwolf, [], [noun(16), animate(16), male(16)], 16)],
	*/
	docontext(Meaning, Meaning, DRS, NewDRS),
	writeln(NewDRS).

gocontext1 :-
	M=[lex(hij, [], [find(1), noun(1), male(1), singular(1), animate(1)], 1), lex(was, [1, 4], [verb(2), pastTense(2), eat(1), eat(4), singular(1), noun(1), before(1), prep(4), after(4)], 2), lex(groot, [], [noun(3)], 3), lex(en, [3, 5], [npconj(4), eat(3), eat(5), noun(3), before(3), noun(5), after(5)], 4), lex(verschrikkelijk, [], [noun(5)], 5)],
	docontext(M,M,drs([2, 5, 8, 11, 15], [in(15, 2), midden(2), van(2, 5), hartje(5), van(5,8), binnenste(8), van(8, 11), gebergte(11), muiskleurig(11), woonde(15),weerwolf(15)]),ND),
	writeln(ND).

%bind new referents
dobind([], _, DRS, DRS).
dobind([lex(Word, Vars, Feats, Id) | Rest], M, drs(Ref, Cond), drs(NewRef, Cond)) :-
	dobind(Rest, M, drs(Ref, Cond), drs(R, Cond)),
	((member(bind(V), Feats) ; (member(find(V), Feats), var(V))) ->
		V = Id,
		%Add variable to M:
		member(lex(Word, Vars, Feats, Id), M),
		%Add new variable to Ref:
		union(R, [V], NewRef)
	;
		% ?! nonvar(Ref),
		NewRef = R).

% wrapper
docontext(Meaning, Meaning, DRS, NewDRS) :-
	dobind(Meaning, Meaning, DRS, Tmp),
	Tmp = drs(Ref, Cond),
	%handle negation
	((select(lex(_, _, C, _), Meaning, Rest), member(neg(_), C)) ->
		docontext(Rest, Rest, drs([], []), drs(NewRef, TempCond)),
		subtract(TempCond, Cond, NewCond),
		NewDRS = drs(Ref, [not(drs(NewRef, NewCond)) | Cond])
	;
		% handle sentence conjunction
		((select(lex(_, _, D, _), Meaning, _Rest), member(conn(_), D)) ->
			append(A, [lex(_,_,D,_)|B], Meaning),
			docontext(A, A, DRS, drs(NewRef1, TempCond1)),
			docontext(B, B, DRS, drs(NewRef2, TempCond2)),
			% merge DRSes
			union(NewRef1, NewRef2, NewRef3),
			union(NewRef3, Ref, NewRef),
			union(TempCond1, TempCond2, TempCond3),
			union(TempCond3, Cond, NewCond),
			NewDRS = drs(NewRef, NewCond)
		;
			% handle universal quantification
			((select(lex(_, _, E, _), Meaning, Rest), member(univ(_), E)) ->
				select(eat(A), E, ER), %variable
				select(eat(B), ER, _), %sentence
				select(lex(W,_V,_F,A), Rest, RRest),
				%one-word hack for variable:
				Pred =.. [W, A],
				DRS1 = drs([A], [Pred]),
				%AM = [lex(W,V,F,A)], %plus more words?
				%eg. iedere donkere avond
				%docontext(AM, AM, drs([],[]), DRS1),
				docontext(RRest, RRest, drs([],[]), DRS2),
				DRS2 = drs(Ref2, Cond2),
				subtract(Ref2, Ref, NRef2),
				subtract(Cond2, Cond, Cond3),
				union(Cond, [forall(DRS1, drs(NRef2, Cond3))], NewCond),
				NewDRS = drs(Ref, NewCond)
			;
				%normal sentence, stop recursing
				context(Meaning, Meaning, Tmp, NewDRS)))).

context([], _, NewDRS, NewDRS).
context([lex(Word, Vars, Feats, Id) | Rest], M, drs(Ref, Cond), Result) :-
	% add conditions to DRS
	% normal words, ie., neither a determiner or pronoun, has arguments:
	(\+ (member(det(_), Feats) ; member(npconj(_), Feats) ; member(pronoun(_), Feats) ; Vars = []) ->
		% handle NP conjunctions and copula
		(member(eat(X), Feats), member(lex(_,_,XFeats,X), M), member(npconj(X), XFeats) ->
			select(eat(A), XFeats, XRest),
			select(eat(B), XRest, _),
			(Vars = [Y, X] ->
				XVars1 = [Y, A],
				XVars2 = [Y, B]
			;
				XVars1 = [A, Y],
				XVars2 = [B, Y]),
			((deref(XVars1, M, DerefVars1),
			  deref(XVars2, M, DerefVars2)) ->
				Pred1 =.. [Word | DerefVars1],
				Pred2 =.. [Word | DerefVars2],
				union(Ref, DerefVars1, Tmp),
				union(Tmp, DerefVars2, NewRef)
			;
				%copula, verb has no meaning
				member(lex(Word1, _,_, A), M),
				member(lex(Word2, _,_, B), M),
				Pred1 =.. [Word1, Y],
				Pred2 =.. [Word2, Y],
				union(Ref, [Y], NewRef)),
			union(Cond, [Pred1, Pred2], NewCond)
		;
			%resolve word IDs to discourse referents
			(deref(Vars, M, DerefVars) ->
				Pred =.. [Word | DerefVars],
				union(Ref, DerefVars, NewRef)
			;
				%copula, verb has no meaning
				% eg. hij was groot:
				% get ref from 'hij', condition from 'groot'
				select(eat(A), Feats, XRest),
				select(eat(B), XRest, _),
				member(lex(_W,_,AF,A), M),
				member(lex(Word,_,_,B), M),
				member(bind(A), AF),
				Pred =.. [Word, A],
				union(Ref, [A], NewRef)),
			union(Cond, [Pred], NewCond)),
		context(Rest, M, drs(NewRef, NewCond), Result)
	;	%handle determiners
		((member(det(_), Feats) ; member(pronoun(_), Feats)) ->
			(member(find(F), Feats)
			;
			member(bind(F), Feats)), 
			%recurse until word which hasn't eaten (noun)
			findconditions(F, Feats, M, Preds),
			union(Cond, Preds, NewCond),
			context(Rest, M, drs(Ref, NewCond), Result)
		;
			% a word which hasn't eaten anything but is
			% eaten directly by a verb should bind a new referent
			% and be added as condition.
			((member(lex(_,_,VFeat,_), M), 
			member(eat(Id), VFeat), 
			(member(verb(_), VFeat) ; member(prep(_), VFeat))) ->
				Pred =.. [Word, Id],
				union(Cond, [Pred], NewCond),
				union(Ref, [Id], NewRef),
				context(Rest, M, drs(NewRef, NewCond), Result)
			;
				% other words without arguments are ignored:
				context(Rest, M, drs(Ref, Cond), Result)))).

% eg. de -> rode -> kat should yield [kat, rode]
findconditions(_F, Feats, _Meaning, []) :-
	\+ member(eat(_X), Feats).
findconditions(F, Feats, Meaning, [Pred | Tail]) :-
	member(eat(X), Feats),
	select(lex(AteWord, _, NFeats, X), Meaning, Rest),
	Pred =.. [AteWord, F],
	findconditions(F, NFeats, Rest, Tail).

% dereference word IDs to their original discourse referents
% (ie., word ID from when referent was introduced)
deref([], _Meaning, []).
deref([V | Vars], Meaning, [R | RVars]) :-
	deref(Vars, Meaning, RVars),
	%find word referred to:
	select(lex(_, _, Feats, V), Meaning, Rest),
	%either the discourse referent has been found:
	(member(find(R), Feats)
	;
	%or it has or will be bound:
	member(bind(R), Feats)
	;
	% implicit bind: bare nouns
	(member(lex(_,_, Feats2, _), Meaning), 
	member(eat(V), Feats2),
	member(verb(_), Feats2),
	R = V)
	;
	%recurse (determiner contains find/bind).
	(\+ member(bind(_), Feats),
	\+ member(find(_), Feats),
	((member(verb(_), Feats) 
	; member(prep(_), Feats)
	; member(npconj(_), Feats)
	; member(adv(_), Feats)) ->
		% resolve verb to one of its arguments 
		%(which argument is part of ambiguity of language...)
		member(eat(Foo), Feats)
	;
		%backwards: eg. kat -> rode -> de 
		member(lex(_,_, Feats2, Foo), Meaning), 
		member(eat(V), Feats2)),
	% prevent cycles by passing Rest, ie., without the word we just tried:
	deref([Foo], Rest, [R]))).
