计算Prolog程序中两个节点之间的路径数

时间:2017-10-30 18:43:29

标签: algorithm graph prolog graph-traversal

我需要一些帮助来计算可以到达目标节点的组合数。

我找到了寻找不同路径的程序。但最后我需要一些查询

%Edge List (Knowledge Base)

edge(1,2).
edge(1,4).
edge(2,4).
edge(3,6).
edge(3,7).
edge(4,3).
edge(4,5).
edge(5,6).
edge(5,7).
edge(6,5).
edge(7,5).
edge(8,6).
edge(8,7).

%Program

path(X,Y,[X,Y]):- edge(X,Y).
path(X,Y,[X|Xs]):- edge(X,W), path(W,Y,Xs).

-------------------------------------------------

%Query
path(1, 7, P).

%Results
Z = [1, 2, 4, 3, 6, 5, 7];
Z = [1, 2, 4, 3, 6, 5, 6, 5, 7];
.........................

但是,如果我想运行一个查询,告诉我这些路径的数量。

?-path(1, 7, count). 

should return 2

1 个答案:

答案 0 :(得分:1)

首先,你的答案会进入周期并且不会终止,你可以保留一份你访问过的列表,以避免两次访问相同的节点:

path(X,Y,L):-path(X,Y,L,[X]).

path(X,Y,[X,Y],L):- \+member(Y,L),edge(X,Y).
path(X,Y,[X|Xs],L):- edge(X,W),\+ member(W,L) ,path(W,Y,Xs,[W|L]).

现在,如果您查询:

?- path(1, 7, P).
P = [1, 2, 4, 3, 7] ;
P = [1, 2, 4, 3, 6, 5, 7] ;
P = [1, 2, 4, 5, 7] ;
P = [1, 4, 3, 7] ;
P = [1, 4, 3, 6, 5, 7] ;
P = [1, 4, 5, 7] ;
false.

因此有效路径不是2,因为上述六条路径都是有效的。

现在计算你可以尝试的路径:

findall(P, path(1,7,P), Paths), length(Paths, N).

正如评论中所建议的那样,但这并不是非常有效,因为您需要首先构建所有路径的列表并计算长度。

如果你正在使用Swipl,你可以尝试使用失败驱动的循环来计算所有可能的路径,并使用nb_getval/2nb_setval/2来计算:

count(X,Y):-
            nb_setval(counter, 0),
            path(X,Y,_),
            nb_getval(counter, Value),
            New_value is Value+1,
            nb_setval(counter, New_value),
            fail;
            nb_getval(counter, Value),
            write(Value).

示例:

?- count(1,7).
6
true.