Prolog未加权图形的距离减少了1 [英] Prolog unweighted graph distances off by 1

查看:88
本文介绍了Prolog未加权图形的距离减少了1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在尝试查找未加权图的路径及其长度.这是我的代码;您为其指定了一个关系,一个起点和一个终点以及长度.该代码有效,但是返回的长度比所需的长度短1.

So I am trying to find paths and their lengths for unweighted graphs. Here is my code; you give it a relation, a start, and end, as well as the length. The code works however it returns a length that is 1 less than needed.

:- 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,但是给出了诸如

All these edges have weight/distance of 1 however given a query such as

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

返回的每个长度都应比其少1.

every length returned is 1 less then it should be.

任何有帮助的建议.

推荐答案

我不是尝试根据经验来确定您在谓词travel中计算路径长度的方式,而是在处理列表到计算另一个属性并不难,而且通常会完成.

In stead of trying to fix the way you compute the length of the path in your predicate travel from experience I know that refactoring Prolog code when processing list to calculate another property is not hard and commonly done.

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

So instead this refactors the predicate reverse/2. To refactor reverse/2 we will first need working code for 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以计算长度.

Now to refactor rev/2 to calculate the length.

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的代码中不再需要的部分即可.

Lastly just modify your code to use rev_n/2 and remove the no longer needed portions of your code that calculated 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.

这篇关于Prolog未加权图形的距离减少了1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆