8

我目前正在开发一个递归 Prolog 程序,将路线链接在一起,以创建伯明翰地区的基本GPS。目前我可以得到这样的输出:

输入

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
4

4 回答 4

5

详细讨论此类事情的一本书是 Michael A. Covington的《Prolog 程序员的自然语言处理》 。

一般来说,你需要做的是

  1. 标记输入
  2. 解析令牌(例如使用 DCG)以获取routeplan/3
  3. 称呼routeplan/3
  4. 在输出的基础上生成一些英文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]).
于 2009-03-24T11:45:15.427 回答
4

嗯,如果我理解正确,您只是想很好地格式化列表以便打印出来,不是吗?

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

然后打电话给

output_string(P,'',_).

它可能不是很有效,但它可以完成工作。:)

于 2009-03-24T10:47:46.207 回答
2

对于这类事情,我通常会创建 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 谓词的第三个变量是列表列表。此外,它是通过添加到尾部来构建的。如果不是,它应该很容易适应。在评论中询问。

于 2009-04-02T18:14:07.943 回答
0

以下是一些将文件/流中的行读入 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'\n, 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以获取有关如何解析字符串的信息。

于 2009-03-24T10:28:11.587 回答