Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input in Prolog

I'm currently working on a recursive Prolog program to link routes together to create a basic GPS of the Birmingham area. At the moment I can get output as so:

Input

routeplan(selly_oak, aston, P).

Output

P = [selly_oak, edgbaston, ... , aston]

What I would like to do is have my program provide some sort of interface, so if I were to type in something along the lines of:

Route from selly_oak to aston

It would provide me with:

Go from selly_oak to edgbaston
Go from edgbaston to ...
Finally, Go from ... to aston.

Prolog is a powerful language so I assume this is easily possible, however many of the books I've taken out seem to skip over this part. As far as I am aware I have to use something along the lines of write() and read() although the details are unknown to me.

Could anyone here a Prolog novice out with some basic examples or links to further information?

EDIT: A lot of these answers seem very complicated, where the solution should only be around 5-10 lines of code. Reading in a value isn't a problem as I can do something along the lines of:

find:- 
    write('Where are you? '), 
    read(X), 
    nl, write('Where do you want to go? '),
    read(Y), 
    loopForRoute(X,Y).

I'd prefer it if the output could be written out using write() so a new line (nl) can be used, so that it displays like the output above.

If this were my input, how would I then arrange the top routeplan() to work with these inputs? Also, if I were to add the Lines for these stations as an extra parameter how would this then be implemented? All links are defined at the beginning of the file like so:

rlinks(selly_oak, edgbaston, uob_line).
rlinks(edgbaston, bham_new_street, main_line).

Therefore, with this information, it'd be good to be able to read the line as so.

Go from selly_oak to edgbaston using the uob_line
Go from edgbaston to ... using the ...
Finally, go from ... to aston using the astuni_line
like image 762
Mike B Avatar asked Mar 24 '09 09:03

Mike B


2 Answers

A book which discusses such things in detail is Natural Language Processing for Prolog Programmers by Michael A. Covington.

In general, what you need to do is

  1. Tokenize the input
  2. Parse the tokens (e.g. with DCG) to get the input for routeplan/3
  3. Call routeplan/3
  4. Generate some English on the basis of the output of routeplan/3

Something like this (works in SWI-Prolog):

% Usage example:
%
% ?- query_to_response('Route from selly_oak to aston', Response).
%
% Response = 'go from selly_oak to edgbaston then go from edgbaston
%         to aston then stop .'
%
query_to_response(Query, Response) :-
    concat_atom(QueryTokens, ' ', Query), % simple tokenizer
    query(path(From, To), QueryTokens, []),
    routeplan(From, To, Plan),
    response(Plan, EnglishTokens, []),
    concat_atom(EnglishTokens, ' ', Response).

% Query parser
query(path(From, To)) --> ['Route'], from(From), to(To).
from(From) --> [from], [From], { placename(From) }.
to(To) --> [to], [To], { placename(To) }.

% Response generator
response([_]) --> [stop], [.].
response([From, To | Tail]) -->
    goto(path(From, To)), [then], response([To | Tail]).
goto(path(From, To)) --> [go], from(From), to(To).

% Placenames
placename(selly_oak).
placename(aston).
placename(edgbaston).

% Mock routeplan/3
routeplan(selly_oak, aston, [selly_oak, edgbaston, aston]).
like image 181
Kaarel Avatar answered Sep 22 '22 22:09

Kaarel


Hm, if I understand you correctly you just want to format the list nicely for printing out, no?

In SWI-Prolog this works:

output_string([A,B],StrIn,StrOut) :-
 concat_atom([StrIn, 'Finally, Go from ', A, ' to ', B, '.'],StrOut),
 write(StrOut).

output_string([A,B|Rest],StrIn,StrOut) :-
 concat_atom([StrIn,'Go from ', A, ' to ', B, '.\n'],StrAB),
 output_string([B|Rest],StrAB,StrOut).

then call with

output_string(P,'',_).

It's probably not very efficient, but it does the job. :)

like image 30
pfctdayelise Avatar answered Sep 22 '22 22:09

pfctdayelise