0
votes

I have some problems with a list structure in swi-prolog.

rlTopic([
    [
        [noun],                          % find match for this          
        [
            [ 
                grammar([noun],1),       % use one of this          
                grammar([det,noun],1)           
            ],
            [
                noun(fox,1),               % fill one of the grammars
                det(the,1),                % with these words
                noun(cat,1)
            ]
        ]
    ],
    [
        [det,adj,noun],                                 
        [
            [ 
                grammar([verb,adj],1),       % use one of this          
                grammar([det,noun],1)           
            ],
            [
                det(the,1),               % fill one of the grammars
                adj(quick,1),             % with these words
                noun(cat,1),
                verb(ran,1)
            ]
        ]
    ],
 ....

I try to find a match (from input) with the [noun]. After this, get one of the grammars in the next level and match them with the words. Finding the grammars works fine right now, but I have problems to insert the words to the grammar.

My code right now:

get_keyword(KeyList, [KeyList,_]).
get_response(RespList, [_, RespList]).

find_grammar([Grammars,Words],AtomGrammar):- 
            is_list(Grammars),
            find_grammar(Grammars,AtomGrammar),!;
            AtomGrammar = Grammars.

find_grammar(_,_).

find_match(Input, [FirstRecord|RestDatabase], ListOfResponse):-
    get_keyword(Keyword, FirstRecord),
    Keyword == Input, get_response(ListOfResponse, FirstRecord), !;
    find_match(Input, RestDatabase, ListOfResponse).

find_match(_, [_], _).

test(Input):-       
    rlTopic(ListOfRecord),
    find_match(Input, ListOfRecord, ListOfResponse), 
    find_grammar(ListOfResponse,G).

For the input test([det,adj,noun]), the output should one of the grammars filled with the words, like run quick.

Thanks in advance!

1
What kind of Input did you provide on your query? Was it just [noun]? Also, G is singleton in test(Input) clause. Is that intentional? - lurker
the input is a list. e.g. test([noun]) or test([det,noun,...]). My intention is to use the G for the next clause. - 74ck
I mean specifically. I know it's a list. When you ran your example query, what did you give it? What result did you expect? What result did you get? What result do you expect when you enter test([noun]).? - lurker
Ah sorry. E.g. : test([det,noun,adj]), the output result should something like the quick fox. If the list [det,adj,noun] is in the structure - 74ck
Are you sure you do not want to use a DCG? - false

1 Answers

2
votes

I'm not entirely sure I understand what you're trying to do here, I think because we're both being thwarted by the data structures you have created. It looks to me like you're trying to do part-of-speech tagging followed by parsing of a natural language sentence, which is very interesting stuff. This is something I've only ever tinkered with, but there are several good books on this topic, including Ivan Bratko's famous book Prolog Programming for Artificial Intelligence and the lesser-known but very useful Prolog and Natural Language Analysis by Fernando Pereira.

You have a lot of list structure here which seems to be getting in the way, so I'm going to ignore it for now. You can always make a list work like facts in the store using member/2. And your second problem is that I think you want to search noun/2 and det/2 and probably other parts of speech, but you don't know which one you want to search when you're holding onto a word. So I would suggest you replace noun/2 and det/2 and so forth with something like part_of_speech(Word, PartOfSpeech). So this is the database I would start with:

grammar([noun]).
grammar([det,noun]).

part_of_speech(fox, noun).
part_of_speech(the, det).
part_of_speech(cat, noun).

I'm removing the integers because I don't see what their purpose is. From here, it's pretty easy to find a grammar and fill it in with your input:

match(Input, Grammar, Tagged) :-
    grammar(Grammar),
    maplist(match_word, Input, Grammar, Tagged).

match_word(Word, Part, Tag) :-
    part_of_speech(Word, Part),
    Tag =.. [Part, Word].

This produces results like this:

?- match([the,cat], G, T).
G = [det, noun],
T = [det(the), noun(cat)].

?- match([cat], G, T).
G = [noun],
T = [noun(cat)] ;
false.

?- match([the,cat], G, T).
G = [det, noun],
T = [det(the), noun(cat)].

?- match([the,fox], G, T).
G = [det, noun],
T = [det(the), noun(fox)].

I think this is what you want, but I'm not completely sure because I don't see example input/output. This is a simplified solution to a simplified problem; I think if the solution is in the right ballpark, it should be possible to lift it into your rather inconvenient data structure. If it's not, then I would recommend you consider an approach based on using DCGs instead of a rule/match thing like this; it will probably be much cleaner and more straightforward.

Part of speech tagging is definitely an interesting topic within AI, especially "classical" AI, and this approach probably doesn't scale all that nicely.

Also, check out WordNet; there is a Prolog version of their database, which might save you some work.