【问题标题】:Prolog unweighted graph distances off by 1Prolog 未加权图距离减少 1
【发布时间】:2018-12-09 06:23:05
【问题描述】:

所以我试图找到未加权图的路径及其长度。这是我的代码;你给它一个关系,一个开始和结束,以及长度。该代码有效,但是它返回的长度比需要的少 1。

:- use_module(library(lists)).

edge(1,2).    
edge(1,4).    
edge(1,3).    
edge(2,3).    
edge(2,5).    
edge(3,4).    
edge(3,5).    
edge(4,5).

connected(X,Y) :- 
    edge(X,Y) 
    ; 
    edge(Y,X).

path(Rel,A,B,Path,Len) :-    
       travel(Rel,A,B,[A],Q,Len),
       reverse(Q,Path).

travel(Rel,A,B,P,[B|P],L) :-    
       call(Rel, A, B), L is 1 .

travel(Rel,A,B,Visited,Path,L) :-    
       call(Rel,A,C),
       C \== B,
       \+member(C,Visited),
       travel(Rel,C,B,[C|Visited],Path,L1),
       L is L1 + 1.

所有这些边的权重/距离为 1,但是给定查询,例如

?- path(connected, 1, 5, Path, Length).

返回的每个长度都比应有的少 1。

任何有用的建议。

【问题讨论】:

    标签: path prolog graph-theory weighted


    【解决方案1】:

    根据经验,我知道在处理列表以计算另一个属性时重构 Prolog 代码并不难,而且通常可以完成,而不是尝试修复在谓词 travel 中计算路径长度的方式。

    因此,这会重构谓词 reverse/2。要重构reverse/2,我们首先需要reverse/2 的工作代码:

    % Reverse using accumulator
    rev(List,Rev) :-
      rev(List,[],Rev) .
    
    rev([],A,A).
    rev([H|T],A,R) :-
      rev(T,[H|A],R).
    

    rev/2 的示例

    ?- rev([],L).
    L = [].
    
    ?- rev([a],L).
    L = [a].
    
    ?- rev([a,b],L).
    L = [b, a].
    
    ?- rev([a,b,c],L).
    L = [c, b, a].
    

    现在重构rev/2 来计算长度。

    rev_n(List,Rev,N) :-
      rev_n(List,[],Rev,N) .
    
    rev_n([],A,A,0).
    rev_n([H|T],A,R,N) :-
      rev_n(T,[H|A],R,N0),
      N is N0 + 1.
    

    rev_n/2 的示例

    ?- rev_n([],L,N).
    L = [],
    N = 0.
    
    ?- rev_n([a],L,N).
    L = [a],
    N = 1.
    
    ?- rev_n([a,b],L,N).
    L = [b, a],
    N = 2.
    
    ?- rev_n([a,b,c],L,N).
    L = [c, b, a],
    N = 3.
    

    最后只需修改您的代码以使用 rev_n/2 并删除计算 N 的代码中不再需要的部分。

    path_2(Rel,A,B,Path,Len) :-
        travel_2(Rel,A,B,[A],Q),
        rev_n(Q,Path,Len).
    
    travel_2(Rel,A,B,P,[B|P]) :-
        call(Rel, A, B).
    
    travel_2(Rel,A,B,Visited,Path) :-
        call(Rel,A,C),
        C \== B,
        \+member(C,Visited),
        travel_2(Rel,C,B,[C|Visited],Path).
    

    例子:

    ?- path_2(connected, 1, 5, Path, Length).
    Path = [1, 2, 5],
    Length = 3 ;
    Path = [1, 2, 3, 5],
    Length = 4 ;
    Path = [1, 2, 3, 4, 5],
    Length = 5 ;
    Path = [1, 4, 5],
    Length = 3 ;
    Path = [1, 4, 3, 5],
    Length = 4 ;
    Path = [1, 4, 3, 2, 5],
    Length = 5 ;
    Path = [1, 3, 5],
    Length = 3 ;
    Path = [1, 3, 4, 5],
    Length = 4 ;
    Path = [1, 3, 2, 5],
    Length = 4 ;
    false.
    

    更实用的方法是只使用length/2

    path_3(Rel,A,B,Path,Len) :-
        travel_2(Rel,A,B,[A],Q),
        reverse(Q,Path),
        length(Path,Len).
    
    ?- path_3(connected, 1, 5, Path, Length).
    Path = [1, 2, 5],
    Length = 3 ;
    Path = [1, 2, 3, 5],
    Length = 4 ;
    Path = [1, 2, 3, 4, 5],
    Length = 5 ;
    Path = [1, 4, 5],
    Length = 3 ;
    Path = [1, 4, 3, 5],
    Length = 4 ;
    Path = [1, 4, 3, 2, 5],
    Length = 5 ;
    Path = [1, 3, 5],
    Length = 3 ;
    Path = [1, 3, 4, 5],
    Length = 4 ;
    Path = [1, 3, 2, 5],
    Length = 4 ;
    false.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多