在SWI prolog。为什么我的路径输出两次,我怎样才能做出最短路径?

时间:2018-03-29 22:34:26

标签: path 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').

在path_to_phone中,如果一个房间有响铃,那么它将继续查看该房间的路径。 我不确定为什么路径输出两次。基于此,我怎样才能走最短的路径来获得房间。

1 个答案:

答案 0 :(得分:2)

我认为这是因为您以两种方式定义双向图。 你只需要一种方式。 我的意思是你定义"触摸(2,1)。"和"触摸(1,2)。"和 邻近/ 2也是。

这些定义都用于表示双向图。 需要两个中的任何一个,但两者都是多余的。

删除下面的冗余术语后,您的代码将会收集。 (旅行/ 2也需要修改如下)。

抱歉我的英语不好。

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').

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. findalllength来获得答案,因为问题的大小非常小。 当节点数很大时,您可以使用sort算法来获得最短路径。它需要实现breadth first search数据结构。