我需要创建一个谓词isConnected/1
,它将图形作为参数,并确定这些对之间是否存在无向路径。
假设我有一个边缘列表(其中G
是图形):
isEdge(G,1,2).
isEdge(G,2,3).
isEdge(G,4,5).
因为3和4之间没有边缘,所以这应该失败 我该如何处理这个问题?我是否必须遍历每条边并记录列表中的边?还是有更好的方法来做到这一点?
答案 0 :(得分:2)
一旦使用图论库,这很容易。我首先使用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].
您可以通过各种方式自己实现这一点(如果您想成为更好的程序员,那么建议您使用现有的库),而不是依赖现有的库。实现此形式的一种方法是使用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).