Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog程序未退出_Prolog - Fatal编程技术网

Prolog程序未退出

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,

我已经编写了prolog程序,它采用初始坐标、拾取坐标和最终坐标(x、y、z)。代理应通过拾取坐标到达最终坐标。当我运行查询时,程序将无限期运行。我假设这是因为有大量的组合可供搜索。因此,我减少了
中的限制条件(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。
最有可能是循环,请访问