Mapping Prolog中的输入

Mapping Prolog中的输入,mapping,prolog,dcg,Mapping,Prolog,Dcg,我目前正在开发一个递归Prolog程序,将路线连接在一起,创建伯明翰地区的基本GPS。目前,我可以获得如下输出: 输入 routeplan(selly_oak, aston, P). P = [selly_oak, edgbaston, ... , aston] 输出 routeplan(selly_oak, aston, P). P = [selly_oak, edgbaston, ... , aston] 我想做的是让我的程序提供某种类型的接口,因此如果我要键入以下内容: Route

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

输入

routeplan(selly_oak, aston, P).
P = [selly_oak, edgbaston, ... , aston]
输出

routeplan(selly_oak, aston, P).
P = [selly_oak, edgbaston, ... , aston]
我想做的是让我的程序提供某种类型的接口,因此如果我要键入以下内容:

Route from selly_oak to aston
find:- 
    write('Where are you? '), 
    read(X), 
    nl, write('Where do you want to go? '),
    read(Y), 
    loopForRoute(X,Y).
它将为我提供:

Go from selly_oak to edgbaston
Go from edgbaston to ...
Finally, Go from ... to aston.
Prolog是一种功能强大的语言,所以我认为这是很容易做到的,不过我拿出的许多书似乎都跳过了这一部分。据我所知,我必须使用类似write()和read()的东西,尽管细节我不知道

这里有没有人能提供一些基本的例子或链接到更多信息的序言新手

编辑:这些答案中有很多看起来非常复杂,解决方案应该只有大约5-10行代码。读入一个值不是问题,因为我可以做以下几点:

Route from selly_oak to aston
find:- 
    write('Where are you? '), 
    read(X), 
    nl, write('Where do you want to go? '),
    read(Y), 
    loopForRoute(X,Y).
我更喜欢使用write()写出输出,这样就可以使用新行(nl),这样就可以像上面的输出一样显示

如果这是我的输入,我将如何安排top 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

以下是几个谓词,用于将文件/流中的行读入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).

然后,看一看s,了解如何解析字符串。

Hm,如果我理解正确,您只想将列表格式化以便打印出来,不是吗

在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,'',_).

这可能不是很有效,但它确实起到了作用。:)

一本详细讨论这些事情的书是Prolog程序员的自然语言处理 迈克尔·科文顿著

一般来说,你需要做的是

  • 将输入标记化
  • 解析令牌(例如使用DCG)以获取
    routeplan/3
  • 呼叫
    routeplan/3
  • 根据
    routeplan/3
  • 类似这样的内容(在SWI Prolog中工作):


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

    您使用的Prolog版本是什么?rlinks/3功能正常吗?即,它是否将一对“站”映射到一条“线”?或者“线路”信息现在是否以某种方式由routeplan/3提供?是的,rlinks/3将发挥作用,并将站点映射到线路。站点也可能出现在多行上。唯一不同的是,我会保留一个行列表,而不是将其全部连接到一个字符串中。它为以后如何使用它提供了更大的灵活性。Prolog中的NLP让你回忆起许多深夜大学的记忆。为什么是“列表列表”?如果您知道内部列表始终有3个元素,那么请在其中使用非列表项,即[link(a,B,Method)| Rest]。1)您关于引导的说法是正确的,我已经删除了括号。2) 列表列表更容易生成。另一方面,如果明确定义了搜索空间,则可以使用您的方法。3) 这只是偏好——它们在功能上是一样的。不知道为什么会被否决。根据这个问题目前的阅读方式,我想说这个答案与提问者想要的非常接近。这就是我所要求的,这是一个很好的解释。谢谢大家!@汤姆·赖特,我真的不明白你对(2)的反应。另外,您为什么假设打印路径/1的输入顺序相反,即第一步是列表中的最后一个元素。这看起来很奇怪。