Tom Dawson
Tom Dawson

Reputation: 43

list intersection, Prolog

ok, so there's basically 3 tasks this program must carry out:

  1. Parse a sentence given in the form of a list, in this case (and throughout the example) the sentence will be [the,traitorous,tostig_godwinson,was,slain]. (its history, don't ask!) so this would look like:

    sentence(noun_phrase(det(the),np2(adj(traitorous),np2(noun(tostig_godwinson)))),verb_phrase(verb(slain),np(noun(slain)))).
    
  2. use the parsed sentence to extract the subject, verb and object, and output as a list, e.g. [tostig_godwinson,was,slain] using the current example. I had this working too until I attempted number 3.

  3. use the target list and compare it against a knowledge base to basically answer the question you asked in the 1st place (see code below) so using this question and the knowledge base the program would print out 'the_battle_of_stamford_bridge' as this is the sentence in the knowledge base with the most matches to the list in question

so here's where i am so far:

history('battle_of_Winwaed',[penda,       king_of_mercia,was,slain,killed,oswui,king_of_bernicians, took_place, '15_November_1655']).

history('battle_of_Stamford_Bridge',[tostig_godwinson,herald_hardrada,was,slain, took_place, '25_September_1066']).

history('battle_of_Boroughbridge',[edwardII,defeated,earl_of_lancaster,execution, took_place, '16_march_1322']).

history('battle_of_Towton',[edwardIV,defeated,henryVI,palm_Sunday]).

history('battle_of_Wakefield',[richard_of_york, took_place, 
'30_December_1490',was,slain,war_of_the_roses]).

history('battle_of_Adwalton_Moor',[earl_of_newcastle,defeats,fairfax, took_place, '30_June_1643',battle,bradford,bloody]).

history('battle_of_Marston_Moor',[prince_rupert,marquis_of_newcastle,defeats,fairfax,oliver_cromwell,ironsides, took_place, 
'2_June_1644', bloody]).

noun(penda).
noun(king_of_mercia).
noun(oswui).
noun(king_of_bernicians).
noun('15_November_1655').
noun(tostig_godwinson).
noun(herald_hardrada).
noun('25_September_1066').
noun(edwardII).
noun(earl_of_lancaster).
noun('16_march_1322').
noun(edwardIV).
noun(henryVI).
noun(palm_Sunday).
noun(richard_of_york).
noun('30_December_1490').
noun(war_of_the_roses).
noun(earl_of_newcastle).
noun(fairfax).
noun('30_June_1643').
noun(bradford).
noun(prince_rupert).
noun(marquis_of_newcastle).
noun(fairfax).
noun(oliver_cromwell).
noun('2_June_1644').
noun(battle).
noun(slain).
noun(defeated).
noun(killed).
adj(bloody).
adj(traitorous).
verb(defeats).
verb(was).
det(a).
det(the).
prep(on).

best_match(Subject,Object,Verb):-
        history(X,Y),
        member(Subject,knowledgebase),
        member(Object,knowledgebase),
        member(Verb,knowledgebase),
        write(X),nl,
        fail.
micro_watson:- write('micro_watson: Please ask me a question:'), read(X), 
sentence(X,Sentence,Subject,Object,Verb),nl,write(Subject),nl,write(Verb),nl,write(Object).

sentence(Sentence,sentence(Noun_Phrase, Verb_Phrase),Subject,Object,Verb):-
    np(Sentence,Noun_Phrase,Rem),
    vp(Rem,Verb_Phrase),
    nl, write(sentence(Noun_Phrase,Verb_Phrase)),
        noun(Subject),
    member(Subject,Sentence),
        noun(Object),
    member(Object,Rem),
    verb(Verb),
    member(Verb,Rem),
        best_match(Subject,Object,Verb).

member(X,[X|_]).
member(X,[_|Tail]):-
    member(X,Tail).
np([X|T],np(det(X),NP2),Rem):-
    det(X),
    np2(T,NP2,Rem).
np(Sentence,Parse,Rem):- np2(Sentence,Parse,Rem).
np(Sentence,np(NP,PP),Rem):-
        np(Sentence,NP,Rem1),
        pp(Rem1,PP,Rem).
np2([H|T],np2(noun(H)),T):-noun(H).
np2([H|T],np2(adj(H),Rest),Rem):- adj(H),np2(T,Rest,Rem).
pp([H|T],pp(prep(H),Parse),Rem):-
    prep(H),
    np(T,Parse,Rem).
vp([H|[]],verb(H)):-
    verb(H).
vp([H|T],vp(verb(H),Rest)):-
    verb(H),
    pp(T, Rest,_).
vp([H|T],vp(verb(H),Rest)):-
    verb(H),
    np(T, Rest,_).

As i said i had number 2 working until i tried number 3, now it just prints the parsed sentence out and then give me a 'Error: out of local stack message' any help is greatly appreciated! So at the top is the knowledge base with which we are comparing out list to find the best match, these are called (albeit incorrectly at this stage) by the best_match method, which executes immediately after the sentence method which parses the sentence and extract the key words. Also i apologise if the code is terribly laid out! Cheers

Upvotes: 3

Views: 773

Answers (1)

ynka
ynka

Reputation: 1497

I assume the person who posted this is never coming back, I wanted to remind myself some prolog, so here it is.

There are two major issues with this code, apart from the fact that there are still some logical problems in some predicates.

Problem 1: You ignored singleton warnings, and they usually are something not to be ignored. The best match predicate should look like this:

best_match(Subject,Object,Verb):-
        history(X,Y),
        member(Subject,Y),
        member(Object,Y),
        member(Verb,Y),
        write(X),nl,
        fail.

The other warning was about the Sentence variable in the sentence predicate, so it goes like this:

sentence(X,Subject,Object,Verb),nl,write(Subject),nl,write(Verb),nl,write(Object).

sentence(Sentence,Subject,Object,Verb):-

    np(Sentence,_,Rem),     
    vp(Rem,_),  
    nl, 
        noun(Subject),
    member(Subject,Sentence),
        noun(Object),
    member(Object,Rem),
    verb(Verb),
    member(Verb,Rem),
        best_match(Subject,Object,Verb).

Problem 2: I assume you divided the np logic into np and np2 to avoid infinite loops, but then forgot to apply this division just where it was necessary. The longest np clause should be:

np(Sentence,np(NP,PP),Rem):-
        np2(Sentence,NP,Rem1),
        pp(Rem1,PP,Rem).

If you really wanted to allow more complicated np there, which I doubt, you can do it like this:

np(Sentence,np(NP,PP),Rem):-
  append(List1,List2,Sentence),
  List1\=[],
  List2\=[],
  np(List1,NP,Rem1),
  append(Rem1,List2,Rem2),
  pp(Rem2,PP,Rem).

This way you will not end up calling np with the same arguments over and over again, because you make sure that the sentence checked is shorter each time.

Minor issues: (How the program works, after the infinite loop problem has been fixed)

  1. The last vp is repeated
  2. I am not sure about your grammar, and e.g. why "defeated" is a noun...

Just to check that the program works I used the sentence [edwardIV,defeated,henryVI,on,palm_Sunday].

I changed "defeated" to a verb, and also changed the last vp clause to:

vp([H|T],vp(verb(H),Rest)):-
    verb(H),
    np(T,_,Rest1),      
    pp(Rest1, Rest,_).

For the example sentence I got battle_of_Boroughbridge and battle_of_Towton as results.

Upvotes: 3

Related Questions