Prolog - 通过所有节点查找图中节点之间的路径及其距离

时间:2017-12-07 00:29:24

标签: prolog

我是prolog的新手,我完全不明白为什么这段代码不起作用,所以我想找到一条路径及其距离,只需一次通过所有节点然后这里回到第一个节点是我做的:

distance(a,b,5).
distance(b,a,5).
distance(a,c,3).
distance(c,a,3).
distance(c,b,2).
distance(b,c,2).


head([H|List],H).
tail([H|List],List).
%Finding the Cycle
  cycle(Node,Cycle) :-
      distance(Node,Next,D),
      cycle(Node,Next,[Node],Cycle).

  cycle(Curr,Curr,Visited,Cycle) :-
      reverse([Curr|Visited],Cycle).
  cycle(Node,Curr,Visited,Cycle) :-
      \+ member(Curr,Visited),
      distance(Curr,Next,D),
      cycle(Node,Next,[Curr|Visited],Cycle).

    %Finding all the possible paths
    find(Start,Cycle):-findall(Z,cycle(Start,Z),Cycle).

    %Selecting only the cycles that contains all the nodes
    path(Start,Cycle,DT):-find(Start,List),
                        path(Start,Cycle,DT,List).
    path(Start,Cycle,DT,List):-head(List,Cycle),
                            tail(List,T),
                            distanceC(Cycle,DT),
                            pathL(Cycle),
                            path(Start,Cycle,DT,T).
%Calculating the distance of a path
distanceC([_],0).
distanceC([X,Y|Rest],DT):-distance(X,Y,D1),distanceC([Y|Rest],DT1), DT is D1 + DT1.
pathL(H):-      length(H,Z),
                Z==3.
当我开始递归

时,

path(Start,Cycle,DT,List)无法正常工作

1 个答案:

答案 0 :(得分:0)

一种方法:

% We need to know all the nodes to visit
% For our purpose the first node is known
% So we remove it
all_the_nodes_but_Start(Nodes, Start) :-
    setof(A, B^C^distance(A,B,C), Nodes_h),
    select(Start, Nodes_h, Nodes).

% the predicate
circuit(Start, Distance, Path) :-
    % we fetch the nodes
    all_the_nodes_but_Start(Nodes, Start),
    % the working predicate
    circuit(Start, Nodes, Start, 0, Distance, [Start], Path).

% @Start : the first and last node to visit
% @Cur_Nodes : the rest of the nodes to visit
% @Current_Node : the node where we are at present
% @Cur_Dist : ... I think that the rest is clear
circuit(Start, Cur_Nodes, Current_Node, Cur_Dist, Distance, Cur_Path, Path) :-
    % we get a link
    distance(Current_Node, Next_Node, Len),
    % verify that it is not yet visited, getting the rest of nodes to visit
    select(Next_Node, Cur_Nodes, Rest_Nodes),
    % compute the distance
    Next_Dist is Len + Cur_Dist,
    %  compute the next step with a neq node in the current path
    circuit(Start, Rest_Nodes, Next_Node, Next_Dist, Distance, [Next_Node | Cur_Path], Path).

% When all the nodes are visited
circuit(Start, [], Current_Node, Cur_Dist, Distance, Cur_Path, Path) :-
    % get back home
    distance(Current_Node, Start, Len),
    Distance is Cur_Dist + Len,
    % getting the path
    reverse([Start | Cur_Path], Path).

现在,我们得到:

?- circuit(a, Len, Path).
Len = 10,
Path = [a, b, c, a] ;
Len = 10,
Path = [a, c, b, a] ;
false.