确定图表是否在prolog中连接

时间:2014-11-17 02:53:17

标签: prolog graph-traversal transitive-closure meta-predicate

我需要创建一个谓词isConnected/1,它将图形作为参数,并确定这些对之间是否存在无向路径。

假设我有一个边缘列表(其中G是图形):

isEdge(G,1,2).
isEdge(G,2,3).
isEdge(G,4,5).

因为3和4之间没有边缘,所以这应该失败 我该如何处理这个问题?我是否必须遍历每条边并记录列表中的边?还是有更好的方法来做到这一点?

2 个答案:

答案 0 :(得分:2)

解决方案1:使用库

一旦使用图论库,这很容易。我首先使用S-representation重写您的图表:

[1-[2],2-[1,3],3-[2],4-[5],5-[4]]

然后我将使用SWI-Prolog(thanks to Richard O'Keefe and Vitor Santos Costa)中包含的库ugraph

?- use_module(library(ugraph)).
?- G = [1-[2],2-[1,3],3-[2],4-[5],5-[4]], vertices(G, Vs), member(V, Vs), reachable(V, G, Ws).
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 1,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 2,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 3,
Ws = [1, 2, 3] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 4,
Ws = [4, 5] ;
G = [1-[2], 2-[1, 3], 3-[2], 4-[5], 5-[4]],
Vs = [1, 2, 3, 4, 5],
V = 5,
Ws = [4, 5].

解决方案2:"自己做"

您可以通过各种方式自己实现这一点(如果您想成为更好的程序员,那么建议您使用现有的库),而不是依赖现有的库。实现此形式的一种方法是使用closure0/3来实现对二元谓词(由SO用户 false 创建)的自反传递闭包。

如果向数据库添加适当的边:

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

...您现在可以查询:

?- member(V, [1,2,3,4,5]), findall(W, closure0(edge, V, W), Ws).
V = 1,
Ws = [1, 2, 3] ;
V = 2,
Ws = [2, 1, 3] ;
V = 3,
Ws = [3, 2, 1] ;
V = 4,
Ws = [4, 5] ;
V = 5,
Ws = [5, 4].

答案 1 :(得分:2)

假设这是this question的后续行动:

首先,您需要定义连接的含义:

connected_to(R_2, A,B) :-
   (  call(R_2, A,B)
   ;  call(R_2, B,A)
   ).

然后您需要确定节点集。通常给出节点集,但似乎你希望它们通过所有边隐式定义:

rel_nodes(R_2, Nodes) :-
   setof(Node, Next^connected_to(R_2, Node,Next), Nodes).

现在连接意味着每个节点都连接到所有其他节点。

is_connected(R_2) :-
   rel_nodes(R_2, Vs),
   maplist({R_2,Vs}+\V0^setof(V, closure0(connected_to(R_2), V0,V), Vs), Vs).

(所有这些都假设节点实际上是基础术语。)

以下是所有缺少的元谓词声明:

:- meta_predicate connected_to(2,?,?), rel_nodes(2,?), is_connected(2).