我需要一些帮助来计算可以到达目标节点的组合数。
我找到了寻找不同路径的程序。但最后我需要一些查询
%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
答案 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/2
和nb_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.