Prolog 在SWI序言中。为什么我的路径是两次输出的,我怎样才能得到最短路径?

Prolog 在SWI序言中。为什么我的路径是两次输出的,我怎样才能得到最短路径?,prolog,shortest-path,Prolog,Shortest Path,在path_to_phone中,如果一个房间有铃声,那么它将继续查找该房间的路径。 我不知道为什么路径会输出两次。在此基础上,我怎样才能找到最短的路径到达房间。我想这是因为你用两种方式定义了双向图。 你只需要一条路。 我的意思是你定义了“触摸(2,1)”和“触摸(1,2)”,以及 相邻的也有1/2 这些定义都用于表示双向图。 两个都是必需的,但都是多余的 删除下面这样的冗余术语后,您的代码将集体工作。 (travel/2也需要修改,如下所示) 对不起,我的英语不好 为了获得最短路径,在这种情

在path_to_phone中,如果一个房间有铃声,那么它将继续查找该房间的路径。
我不知道为什么路径会输出两次。在此基础上,我怎样才能找到最短的路径到达房间。

我想这是因为你用两种方式定义了双向图。 你只需要一条路。 我的意思是你定义了“触摸(2,1)”和“触摸(1,2)”,以及 相邻的也有1/2

这些定义都用于表示双向图。 两个都是必需的,但都是多余的

删除下面这样的冗余术语后,您的代码将集体工作。 (travel/2也需要修改,如下所示)

对不起,我的英语不好

为了获得最短路径,在这种情况下,您可以使用
findall
length
sort
来获得答案,因为问题的规模非常小。
当节点数较大时,可以使用
宽度优先搜索
算法获得最短路径。需要实现
队列
数据结构。

我认为这是因为您用两种方式定义了双向图。 你只需要一条路。 我的意思是你定义了“触摸(2,1)”和“触摸(1,2)”,以及 相邻的也有1/2

这些定义都用于表示双向图。 两个都是必需的,但都是多余的

删除下面这样的冗余术语后,您的代码将集体工作。 (travel/2也需要修改,如下所示)

对不起,我的英语不好

为了获得最短路径,在这种情况下,您可以使用
findall
length
sort
来获得答案,因为问题的规模非常小。
当节点数较大时,可以使用
宽度优先搜索
算法获得最短路径。需要实现
队列
数据结构。

相邻(RoomA,RoomB):-触摸(RoomA,RoomB);触摸(房间B,房间A)。路径到电话(第一个房间,最后一个房间,路径):-%基本情况铃声(最后一个房间),%触摸(第一个房间,X),旅行(第一个房间,最后一个房间,[第一个房间],Q),反向(Q,路径)。旅行(FirstRoom,LastRoom,P,[LastRoom | P]):-%write('who call this\n'),相邻(FirstRoom,LastRoom)。旅行(FirstRoom,LastRoom,Visited,Path):-触摸(FirstRoom,X),X\==LastRoom,\+会员(X,Visited),%写入(Visited),旅行(X,LastRoom,[X,Visited],Path)。%写入('call?\n')。您可以使用
运算符在所需情况检查结束时说“停止寻找其他解决方案”,否则Prolog将自动返回到最后一点,在那里它有多个可能的答案,并尝试这些答案。正如@TakuKoyahata正确回答的那样,您会遇到双重结果,因为答案在两个方面满足您的条件。在Prolog中,您需要找到一种方法来唯一地定义成功案例,他的答案涵盖了您的特定问题。不要试图使用剪切(
)来解决这种情况。相邻(RoomA,RoomB):-触摸(RoomA,RoomB);触摸(房间B,房间A)。路径到电话(第一个房间,最后一个房间,路径):-%基本情况铃声(最后一个房间),%触摸(第一个房间,X),旅行(第一个房间,最后一个房间,[第一个房间],Q),反向(Q,路径)。旅行(FirstRoom,LastRoom,P,[LastRoom | P]):-%write('who call this\n'),相邻(FirstRoom,LastRoom)。旅行(FirstRoom,LastRoom,Visited,Path):-触摸(FirstRoom,X),X\==LastRoom,\+会员(X,Visited),%写入(Visited),旅行(X,LastRoom,[X,Visited],Path)。%写入('call?\n')。您可以使用
运算符在所需情况检查结束时说“停止寻找其他解决方案”,否则Prolog将自动返回到最后一点,在那里它有多个可能的答案,并尝试这些答案。正如@TakuKoyahata正确回答的那样,您会遇到双重结果,因为答案在两个方面满足您的条件。在Prolog中,您需要找到一种方法来唯一地定义成功案例,他的答案涵盖了您的特定问题。不要试图使用剪切(
)来解决这种情况。
ringing(5).
ringing(9).
ringing(16).

touching(2, 1).
touching(7, 1).
touching(1, 2).
touching(8, 2).
touching(8, 3).
touching(8, 4).
touching(9, 4).
touching(6, 5).
touching(9, 5).
touching(5, 6).
touching(9, 6).
touching(1, 7).
touching(8, 7).
touching(9, 7).
touching(10, 7).
touching(11, 7).
touching(12, 7).
touching(13, 7).
touching(14, 7).
touching(2, 8).
touching(3, 8).
touching(4, 8).
touching(7, 8).
touching(4, 9).
touching(5, 9).
touching(6, 9).
touching(7, 9).
touching(7, 10).
touching(7, 11).
touching(7, 12).
touching(7, 13).
touching(7, 14).
touching(15, 14).
touching(14, 15).
touching(16, 15).
touching(15, 16).

adjacent(RoomA, RoomB) :-
      touching(RoomA, RoomB)
   ;  touching(RoomB, RoomA).

path_to_phone(FirstRoom, LastRoom,Path) :- % Base Case
    ringing(LastRoom),
        %touching(FirstRoom, X),
        travel(FirstRoom, LastRoom, [FirstRoom],Q),
        reverse(Q,Path).

travel(FirstRoom, LastRoom,P, [LastRoom|P]) :-
%   write('who call this\n'),
    adjacent(FirstRoom,LastRoom).
travel(FirstRoom,LastRoom, Visited,Path) :-
    touching(FirstRoom,X),
    X \== LastRoom,
    \+member(X,Visited),
    %write(visited),
    travel(X,LastRoom,[X|Visited],Path).
    %write('call?\n').

ringing(5).
ringing(9).
ringing(16).

touching(2, 1).
touching(7, 1).
%touching(1, 2).
touching(8, 2).
touching(8, 3).
touching(8, 4).
touching(9, 4).
touching(6, 5).
touching(9, 5).
%touching(5, 6).
touching(9, 6).
%touching(1, 7).
touching(8, 7).
touching(9, 7).
touching(10, 7).
touching(11, 7).
touching(12, 7).
touching(13, 7).
touching(14, 7).
%touching(2, 8).
%touching(3, 8).
%touching(4, 8).
%touching(7, 8).
%touching(4, 9).
%touching(5, 9).
%touching(6, 9).
%touching(7, 9).
%touching(7, 10).
%touching(7, 11).
%touching(7, 12).
%touching(7, 13).
%touching(7, 14).
touching(15, 14).
%touching(14, 15).
touching(16, 15).
%touching(15, 16).

adjacent(RoomA, RoomB) :-
      touching(RoomA, RoomB)
   ;  touching(RoomB, RoomA).

path_to_phone(FirstRoom, LastRoom,Path) :- % Base Case
    ringing(LastRoom),
        %touching(FirstRoom, X),
        travel(FirstRoom, LastRoom, [FirstRoom],Q),
        reverse(Q,Path).

travel(FirstRoom, LastRoom,P, [LastRoom|P]) :-
%   write('who call this\n'),
    adjacent(FirstRoom,LastRoom).
travel(FirstRoom,LastRoom, Visited,Path) :-
    adjacent(FirstRoom,X), %touching(FirstRoom,X),
    X \== LastRoom,
    \+member(X,Visited),
    %write(visited),
    travel(X,LastRoom,[X|Visited],Path).
    %write('call?\n').


    [trace]  ?- path_to_phone(2,5,A).
    A = [2, 1, 7, 8, 4, 9, 5] ;
    A = [2, 1, 7, 8, 4, 9, 6, 5] ;
    A = [2, 1, 7, 9, 5] ;
    A = [2, 1, 7, 9, 6, 5] ;
    A = [2, 8, 4, 9, 5] ;
    A = [2, 8, 4, 9, 6, 5] ;
    A = [2, 8, 7, 9, 5] ;
    A = [2, 8, 7, 9, 6, 5] ;
    false.