Prolog程序未退出
我已经编写了prolog程序,它采用初始坐标、拾取坐标和最终坐标(x、y、z)。代理应通过拾取坐标到达最终坐标。当我运行查询时,程序将无限期运行。我假设这是因为有大量的组合可供搜索。因此,我减少了Prolog程序未退出,prolog,Prolog,我已经编写了prolog程序,它采用初始坐标、拾取坐标和最终坐标(x、y、z)。代理应通过拾取坐标到达最终坐标。当我运行查询时,程序将无限期运行。我假设这是因为有大量的组合可供搜索。因此,我减少了中的限制条件(X,Y,Z)。我不熟悉prolog,如有任何帮助,将不胜感激。谢谢 in_range(X,Y,Z):- X > -5, X < 5, Y >= 0, Y < 10, Z > -5,
中的限制条件(X,Y,Z)
。我不熟悉prolog,如有任何帮助,将不胜感激。谢谢
in_range(X,Y,Z):-
X > -5,
X < 5,
Y >= 0,
Y < 10,
Z > -5,
Z < 5.
deliver(Ix,Iy,Iz,Px,Py,Pz,Fx,Fy,Fz):-
in_range(Ix,Iy,Iz),
in_range(Px,Py,Pz),
in_range(Fx,Fy,Fz),
move(Ix,Iy,Iz,Px,Py,Pz),
move(Px,Py,Pz,Fx,Fy,Fz).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1-1,
Y is Y1,
Z is Z1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1-1,
Y is Y1,
Z is Z1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1,
Y is Y1-1,
Z is Z1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1,
Y is Y1-1,
Z is Z1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1,
Y is Y1,
Z is Z1-1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1,
Y is Y1,
Z is Z1-1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1+1,
Y is Y1,
Z is Z1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1+1,
Y is Y1,
Z is Z1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1,
Y is Y1+1,
Z is Z1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1,
Y is Y1+1,
Z is Z1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(X1,Y1,Z1,X2,Y2,Z2):-
X is X1,
Y is Y1,
Z is Z1+1,
in_range(X,Y,Z),
X =:= X2,
Y =:= Y2,
Z =:= Z2;
X is X1,
Y is Y1,
Z is Z1+1,
in_range(X,Y,Z),
move(X,Y,Z,X2,Y2,Z2).
move(6,_,_,_,_,_).
move(-6,_,_,_,_,_).
move(_,11,_,_,_,_).
move(_,-1,_,_,_,_).
move(_,_,6,_,_,_).
move(_,_,-6,_,_,_).
您遇到的是一个无限递归,因为您在执行深度优先搜索时没有跟踪访问的节点,通过跟踪它,您将看到您的搜索在基于第一个移动谓词的(0,0,4)(0,0,5)循环中丢失 表格将适用于SWI Prolog,但让我们借此机会探索便携式解决方案,因为它们将帮助您学习Prolog(以及更广泛的CS) 首先,让我们看一下\u range/3中的
谓词,并将我们的位置转换为术语(如果你碰到“物化”这个词,这就是这样做的)。我们想把我们的位置看作是术语,这样我们就可以把它们作为整体来传递。它也帮助我们思考!我们可以这样定义您的世界中的位置:
% loc(X, Y, Z) is a location in 3D integer co-ordinate space
loc(X, Y, Z) :-
between(-5, 5, X),
between(0, 10, Y),
between(-5, 5, Z).
因此,\u范围/3中的变为\u范围/1中的:
in_range(Loc) :- call(Loc).
作为奖励,您可以生成位置:?-loc(X,Y,Z)。
现在可以整理这些移动谓词,使它们更易于阅读、跟踪和思考。为此,他们只定义了一次移动,最好是保持行程
它们自己的谓词,所以当我们只需要一个步骤时,我们可以单独使用它们。(?-移动(loc(1,1,2),步骤)。
)
现在让我们定义交付谓词in_range/1
可用于检查From
的是否有效,而拾取
和目的地
应自行处理:
deliver(From, Pickup, Dest) :-
in_range(From),
go_to(From, Pickup),
go_to(Pickup, Dest).
到目前为止,我只对代码进行了重构,将谓词分解为更小的定义,以实现更大的通用性和更容易的可读性。防止无限递归的最大变化是转到/2
,它尚未定义。鉴于您正在整数3D坐标空间中进行搜索,最合适的搜索算法是a*,它不仅会排除已访问的搜索位置,而且会首先搜索距离预期目标最近的位置
go_to(Origin, Destination) :-
a_star(Origin, Destination).
% A* for SWI-Prolog
:- use_module(library(heaps)).
% Use to order search, 3D euclidean distance squared
heuristic_distance(loc(X1, Y1, Z1), loc(X2, Y2, Z2), Distance) :-
Distance is (X1 - X2)^2 + (Y1 - Y2)^2 + (Z1 - Z2)^2.
% Add a list of nodes to the heap
open_add_nodes(Heap, [], _, Heap).
open_add_nodes(Heap, [ToAdd|Tail], Dest, Out) :-
heuristic_distance(ToAdd, Dest, Dist),
add_to_heap(Heap, Dist, ToAdd, Heap1),
open_add_nodes(Heap1, Tail, Dest, Out).
% Get an ordered list of reachable locations from the origin
get_reachable(Loc, Locations) :-
setof(L, move(Loc, L), Locations).
% A* search setup
a_star(Origin, Dest) :-
% Create heap of open search nodes
heuristic_distance(Dest, Origin, Dist),
singleton_heap(Open, Dist, Origin),
% Do the search
a_star(Open, Dest, [Origin]).
% Do the A* search
a_star(Open, Dest, Closed) :-
% Get the most promising Node
get_from_heap(Open, _, Loc, RemainingSearch),
% If we've reached the goal, return the Answer
( Dest = Loc
% Otherwise keep searching
; get_reachable(Loc, ReachableLocations),
% Exclude visited nodes
ord_union(Closed, ReachableLocations, Closed1, ToSearch),
% Add new open nodes to search heap
open_add_nodes(RemainingSearch, ToSearch, Dest, Open1),
% Carry on searching
a_star(Open1, Dest, Closed1)
).
现在A*可能需要一点时间来阅读和理解,但是如果我们必须处理X,Y,Z
坐标,而不是位置:每个Loc
,Dest
,Origin
和ToAdd
是一个位置。因为我们的move/2
谓词只需要一个步骤,所以也只能进行编码,所以我们可以选择不使用Prolog的隐式深度优先搜索
所有这些代码都在一个文档中,因此您可以对其进行探索。要了解更多有关搜索算法的信息,我建议使用,4和5封面搜索。对于Prolog实现来说,MIT也很好。您遇到了一个无限递归,因为您在执行深度优先搜索时没有跟踪访问的节点,通过跟踪它,您将看到您的搜索在一个(0,0,4)(0,0,5)循环中丢失,基于第一个移动谓词
表格将适用于SWI Prolog,但让我们借此机会探索便携式解决方案,因为它们将帮助您学习Prolog(以及更广泛的CS)
首先,让我们看一下\u range/3中的谓词,并将我们的位置转换为术语(如果你碰到“物化”这个词,这就是这样做的)。我们想把我们的位置看作是术语,这样我们就可以把它们作为整体来传递。它也帮助我们思考!我们可以这样定义您的世界中的位置:
% loc(X, Y, Z) is a location in 3D integer co-ordinate space
loc(X, Y, Z) :-
between(-5, 5, X),
between(0, 10, Y),
between(-5, 5, Z).
因此,\u范围/3中的变为\u范围/1中的:
in_range(Loc) :- call(Loc).
作为奖励,您可以生成位置:?-loc(X,Y,Z)。
现在可以整理这些移动谓词,使它们更易于阅读、跟踪和思考。为此,他们只定义了一次移动,最好是保持行程
它们自己的谓词,所以当我们只需要一个步骤时,我们可以单独使用它们。(?-移动(loc(1,1,2),步骤)。
)
现在让我们定义交付谓词in_range/1
可用于检查From
的是否有效,而拾取
和目的地
应自行处理:
deliver(From, Pickup, Dest) :-
in_range(From),
go_to(From, Pickup),
go_to(Pickup, Dest).
到目前为止,我只对代码进行了重构,将谓词分解为更小的定义,以实现更大的通用性和更容易的可读性。防止无限递归的最大变化是转到/2
,它尚未定义。鉴于您正在整数3D坐标空间中进行搜索,最合适的搜索算法是a*,它不仅会排除已访问的搜索位置,而且会首先搜索距离预期目标最近的位置
go_to(Origin, Destination) :-
a_star(Origin, Destination).
% A* for SWI-Prolog
:- use_module(library(heaps)).
% Use to order search, 3D euclidean distance squared
heuristic_distance(loc(X1, Y1, Z1), loc(X2, Y2, Z2), Distance) :-
Distance is (X1 - X2)^2 + (Y1 - Y2)^2 + (Z1 - Z2)^2.
% Add a list of nodes to the heap
open_add_nodes(Heap, [], _, Heap).
open_add_nodes(Heap, [ToAdd|Tail], Dest, Out) :-
heuristic_distance(ToAdd, Dest, Dist),
add_to_heap(Heap, Dist, ToAdd, Heap1),
open_add_nodes(Heap1, Tail, Dest, Out).
% Get an ordered list of reachable locations from the origin
get_reachable(Loc, Locations) :-
setof(L, move(Loc, L), Locations).
% A* search setup
a_star(Origin, Dest) :-
% Create heap of open search nodes
heuristic_distance(Dest, Origin, Dist),
singleton_heap(Open, Dist, Origin),
% Do the search
a_star(Open, Dest, [Origin]).
% Do the A* search
a_star(Open, Dest, Closed) :-
% Get the most promising Node
get_from_heap(Open, _, Loc, RemainingSearch),
% If we've reached the goal, return the Answer
( Dest = Loc
% Otherwise keep searching
; get_reachable(Loc, ReachableLocations),
% Exclude visited nodes
ord_union(Closed, ReachableLocations, Closed1, ToSearch),
% Add new open nodes to search heap
open_add_nodes(RemainingSearch, ToSearch, Dest, Open1),
% Carry on searching
a_star(Open1, Dest, Closed1)
).
现在A*可能需要一点时间来阅读和理解,但是如果我们必须处理X,Y,Z
坐标,而不是位置:每个Loc
,Dest
,Origin
和ToAdd
是一个位置。因为我们的move/2
谓词只需要一个步骤,所以也只能进行编码,所以我们可以选择不使用Prolog的隐式深度优先搜索
所有这些代码都在一个文档中,因此您可以对其进行探索。要了解更多有关搜索算法的信息,我建议使用,4和5封面搜索。对于Prolog的实现,同样来自MIT,这是非常好的。很可能您正在循环,一次又一次地访问同一个坐标。如果您运行的是最新版本的SWI Prolog,请使用TablingHanks,它会一次又一次地在相同的坐标中循环。我可以通过删除函数来减少坐标来获得输出。无论如何,我可以添加代码的减量部分,而不会导致无限循环。更简单的方法是使用制表,即,:-table move/6。
最有可能是循环,请访问