SWI Prolog中的寻路(生成和测试方法)

SWI Prolog中的寻路(生成和测试方法),prolog,shortest-path,Prolog,Shortest Path,好的,我正在尝试构建一个路径查找SWI Prolog程序,该程序将网格从知识库中的事实中遍历属性: y_max(Ymax). x_max(Xmax). pick_up(Y,X). 例如,下面的代码表示下面的网格: y_max(6). x_max(6). pick_up(4,4). pick_up(3,2). % 6 | | | | | |F| % ------------- % 5 | | | | | | | % ------------- % 4 | | | |P| | | %

好的,我正在尝试构建一个路径查找SWI Prolog程序,该程序将网格从知识库中的事实中遍历属性:

y_max(Ymax).
x_max(Xmax).
pick_up(Y,X).
例如,下面的代码表示下面的网格:

y_max(6).
x_max(6).
pick_up(4,4).
pick_up(3,2).

% 6 | | | | | |F|
%   -------------
% 5 | | | | | | |
%   -------------
% 4 | | | |P| | |
%   -------------
% 3 | |P| | | | |
%   -------------
% 2 | | | | | | |
%   -------------
% 1 |L| | | | | |
%    1 2 3 4 5 6

% (Note that coordinates will be in the form [Y,X].
其中,F是路径的起点,即[6,6],L是路径的终点[1,1],路径应尽可能多地沿着路径拾取“对象”。因此,在这种情况下,“理想”解决方案是:

% 6 | | | | |X|F|
%   -------------
% 5 | | | |X|X| |
%   -------------
% 4 | |X|X|P| | |
%   -------------
% 3 |X|P| | | | |
%   -------------
% 2 |X| | | | | |
%   -------------
% 1 |L| | | | | |
%    1 2 3 4 5 6
其中路径p为: P=[[6,6]、[6,5]、[5,5]、[5,4]、[4,4]、[4,3]、[4,2]、[3,1]、[2,1]、[1,1]]

我的主要关系是:

solve(P,A) :-
根据给出图形的知识库,返回理想(最短)路径p和A,A为路径拾取的拾取对象数(应为可拾取的最大拾取对象数)

我正在尝试使用生成和测试类型的方法来实现这一点,因为路径的长度无法基于知识库(据我所知),我假设我将不得不递归地生成和测试坐标?我尝试在不使用任何库的情况下进行此练习,以便真正掌握这种Prolog编程风格,即生成和测试路径

这是我到目前为止所得到的,但我似乎无法正确地得到它。相反,它只会给我一个错误:每次都超出全局堆栈

% FACTS
y_max(6).
x_max(6).
pick_up(5,5).
pick_up(4,4).
pick_up(2,2).

solve(A,P) :-
   y_max(Y), x_max(X), aggregate_all(count,pick_up(O,E),C),
   A = C, append(P,[Y,X],Np), build_path(Y,X,Y,X,P),                                                                                                                                         
   % I'm assuming at this point the list is generated, now to test...
   member([Y,X],P), is_last([1,1],P), member([O,E],P).

% cases to end recursion - not sure if I'm doing this part correctly...                                                                                                                                        
build_path(Y,X,1,2,P) :- append(P,[1,1],Q), P = Q.
build_path(Y,X,2,1,P) :- append(P,[1,1],Q), P = Q.

% recursive case                                                                                                                                                                                               
build_path(Y,X,PrevY,PrevX,P) :-
   integer(NextY), integer(NextX),
   NextY =< Y, NextY >= 1,
   NextX =< X, NextY >= 1,
   (  (NextY =:= PrevY-1, NextX =:= PrevX)
   ;  (NextY =:= PrevY+1, NextX =:= PrevX)
   ;  (NextY =:= PrevY, NextX =:= PrevX+1)
   ;  (NextY =:= PrevY, NextX =:= PrevX-1)
   ),
   append(P,[NextY,NextX],Np),
   build_path(Y,X,NextY,NextX,Np).

is_last([Y,X],[H|[]]) :- H = [Y,X].
is_last([Y,X],[H|T]) :- is_last([Y,X],T).
%FACTS
y_max(6)。
x_max(6)。
拾起(5,5)。
拾起(4,4)。
拾起(2,2)。
求解(A,P):-
y_max(y)、x_max(x)、聚合_all(计数、拾取(O、E)、C),
A=C,追加(P[Y,X],Np),构建路径(Y,X,Y,X,P),
%我假设此时列表已生成,现在要测试。。。
成员([Y,X],P),是最后的成员([1,1],P),成员([O,E],P)。
%案例结束递归-不确定我是否正确地完成了这部分。。。
构建路径(Y,X,1,2,P):-append(P[1,1],Q),P=Q。
构建路径(Y,X,2,1,P):-append(P[1,1],Q),P=Q。
%递归案例
构建路径(Y,X,PrevY,PrevX,P):-
整数(NextY),整数(NextX),
NextY==1,
NextX==1,
((NextY=:=PrevY-1,NextX=:=PrevX)
(NextY=:=PrevY+1,NextX=:=PrevX)
(NextY=:=PrevY,NextX=:=PrevX+1)
(NextY=:=PrevY,NextX=:=PrevX-1)
),
附加(P[NextY,NextX],Np),
构建路径(Y、X、NextY、NextX、Np)。
是最后一个([Y,X],[H |[]):-H=[Y,X]。
is_last([Y,X],[H|T]):-is_last([Y,X],T)。

那么,我做错了什么?我似乎在网上找不到一个类似的例子来给我提供正确的想法。我假设我只是把事情复杂化了,或者没有正确地向Prolog表达某些信息。如果我的解决方案充满了错误,我道歉。我目前只是想了解Prolog。

我没有阅读你的程序但至少这些观点似乎是错误的:

  • NextY=:=PrevY-1
    零件应更改为
    NextY is PrevY-1
    =:=
    仅用于比较,不用于设置值

  • 您的代码似乎在
    build\u path
    处处于无限循环中,因为您没有检查下一个协调人是否不在协调人列表中

  • 3.
    integer(NextY)、integer(NextX),
    总是失败,因为它们是新变量,尚未设置任何值,当然它们不是整数

  • 你不需要检查生成的坐标是否在董事会之外

  • 您正在尝试
    深度优先搜索
    算法。在您使此程序工作后,不幸的是,第一个答案将远离最短路径。当您想要获得最短路径时,我建议使用
    广度优先搜索算法


  • 我没有深入阅读您的程序,但至少这些观点似乎不正确:

  • NextY=:=PrevY-1
    零件应更改为
    NextY is PrevY-1
    =:=
    仅用于比较,不用于设置值

  • 您的代码似乎在
    build\u path
    处处于无限循环中,因为您没有检查下一个协调人是否不在协调人列表中

  • 3.
    integer(NextY)、integer(NextX),
    总是失败,因为它们是新变量,尚未设置任何值,当然它们不是整数

  • 你不需要检查生成的坐标是否在董事会之外

  • 您正在尝试
    深度优先搜索
    算法。在您使此程序工作后,不幸的是,第一个答案将远离最短路径。当您想要获得最短路径时,我建议使用
    广度优先搜索算法


  • 下面是一个版本的
    build\u path/N
    ,它似乎可以工作

    build_path(MaxY,MaxX,Y0,X0,P0,P,Is0,Is) :-
      ( Y0 = 1, X0 = 1 ->
        P = P0, Is = Is0
      ; ( Y is Y0 - 1, X is X0
        ; Y is Y0 + 1, X is X0
        ; Y is Y0, X is X0 + 1
        ; Y is Y0, X is X0 - 1 ),
        Y =< MaxY, Y >= 1, X =< MaxX, X >= 1, \+ member(Y-X,P0),
        append(P0,[Y-X],P1),
        ( pick_up(Y,X) -> Is1 = [Y-X|Is0] ; Is1 = Is0 ),
        build_path(MaxY,MaxX,Y,X,P1,P,Is1,Is) ).
    
    build_路径(MaxY,MaxX,Y0,X0,P0,P,Is0,Is):-
    (Y0=1,X0=1->
    P=P0,Is=Is0
    (Y是Y0-1,X是X0
    ;Y是Y0+1,X是X0
    ;Y是Y0,X是X0+1
    ;Y是Y0,X是X0-1),
    Y==1,X==1,\+成员(Y-X,P0),
    追加(P0,[Y-X],P1),
    (拾取(Y,X)->Is1=[Y-X | Is0];Is1=Is0),
    构建路径(MaxY,MaxX,Y,X,P1,P,Is1,Is))。
    
    您需要确保它在到达末端正方形时停止,因此需要使用if-then-else或cut


    我添加了一个拾取项目的列表,所以现在您只需要找到路径和列表的最佳组合。

    这里有一个版本的
    build\u path/N
    ,似乎可以工作

    build_path(MaxY,MaxX,Y0,X0,P0,P,Is0,Is) :-
      ( Y0 = 1, X0 = 1 ->
        P = P0, Is = Is0
      ; ( Y is Y0 - 1, X is X0
        ; Y is Y0 + 1, X is X0
        ; Y is Y0, X is X0 + 1
        ; Y is Y0, X is X0 - 1 ),
        Y =< MaxY, Y >= 1, X =< MaxX, X >= 1, \+ member(Y-X,P0),
        append(P0,[Y-X],P1),
        ( pick_up(Y,X) -> Is1 = [Y-X|Is0] ; Is1 = Is0 ),
        build_path(MaxY,MaxX,Y,X,P1,P,Is1,Is) ).
    
    build_路径(MaxY,MaxX,Y0,X0,P0,P,Is0,Is):-
    (Y0=1,X0=1->
    P=P0,Is=Is0
    (Y是Y0-1,X是X0
    ;Y是Y0+1,X是X0
    ;