English 中文(简体)
输入Prolog
原标题:
  • 时间:2009-03-24 09:45:26
  •  标签:

我目前正在编写一个递归 Prolog 程序,将路线连接起来,以创建伯明翰地区的基本 GPS。目前,我的输出如下:

输入 (rù kǒu)

routeplan(selly_oak, aston, P).

输出

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

我想做的是让我的程序提供某种界面,这样如果我输入类似于以下内容的东西:

Route from selly_oak to aston

它会给我提供:

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

Prolog是一种强大的语言,因此我认为这很容易实现,但我借阅的许多书似乎都跳过了这一部分。据我所知,我必须使用类似于write()和read()的内容,尽管细节对我来说是未知的。

有没有人可以给一个Prolog初学者提供一些基本的例子或进一步的信息链接?

编辑:很多答案看起来很复杂,但实际上解决方案只需要5-10行代码。读取值不是问题,我可以通过以下方式处理:

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

我倾向于使用write()将输出写出,这样就可以使用换行符(nl),以便像上面的输出一样显示。

如果这是我的输入,我该如何安排顶部的routeplan()函数来处理这些输入?另外,如果我想将这些站点的线路作为额外的参数添加,该如何实现?所有链接都在文件的开头被定义,就像这样:

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

因此,有了这些信息,能够把这条线读出来是很好的。

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
最佳回答

对于这种情况,我通常会创建shell谓词。所以在你的情况下...

guided:-
    print( Enter your start point ),nl,
    read(Start),
    print( Enter your destination ),nl,
    read(Dest),
    routeplan(Start, Dest, Route),
    print_route(Route).

并且print_route/1可能是类似这样的递归函数:

print_route([]).

print_route([[A,B,Method]|Tail]):-
    print_route(Tail),
    print( Go from  ), print(A),
    print(  to  ), print(B),
    print(  by  ), print(Method), nl.

我已经假设routeplan/3谓词的第三个变量是一个列表的列表。而且它是通过添加到尾部构建的。如果不是,那么适应应该相当容易。在评论中询问。

问题回答

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

通常,您需要做的是

  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

这样的东西(在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]).

嗯,如果我理解正确,您只是想将列表漂亮地格式化以便打印,对吗?

在SWI-Prolog中这个可以工作:

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,  .
 ],StrAB),
 output_string([B|Rest],StrAB,StrOut).

然后打电话联系

output_string(P,  ,_).

可能不是非常有效,但它能完成任务。 :)

以下是将文件/流中的行读入Prolog字符串的一些述语:

%%% get_line(S, CL): CL is the string read up to the end of the line from S.
%%% If reading past end of file, returns  end_of_file  in CL first, raises
%%% an exception second time.
%%% :- pred get_string(+stream, -list(int)).
get_line(S, CL) :-
    peek_code(S, C),
    (   C = -1
    ->  get_code(S, _),
        CL = end_of_file
    ;   get_line(S, C, CL)).

get_line(_, -1, CL) :- !, CL = [].  % leave end of file mark on stream
get_line(S, 0 
, CL) :- !,
    get_code(S, _),
    CL = [].
get_line(S, C, [C|CL]) :-
    get_code(S, _),
    peek_code(S, NC),
    get_line(S, NC, CL).

%% read_lines(L): reads lines from current input to L.  L is a list of list
%% of character codes, newline characters are not included.
%% :- pred read_lines(-list(list(char))).
read_lines(L) :-
    current_input(In),
    get_line(In, L0),
    read_lines(In, L0, L).

%% read_lines(F, L): reads lines from F to L.  L is a list of list of character
%% codes, newline characters are not included.
%% :- pred read_lines(+atom, -list(list(char))).
read_lines(F, L) :-
    fail_on_error(open(F, read, S)),
    call_cleanup((get_line(S, L0),
              read_lines(S, L0, L)),
             close(S)).

read_lines(_, end_of_file, L) :- !, L = [].
read_lines(S, H, [H|T]) :-
    get_line(S, NH),
    read_lines(S, NH, T).

然后,查看有关如何解析字符串的DCG的信息。





相关问题
热门标签