Determining if a graph is connected in a prologue
I need to make a predicate isConnected/1
that takes a graph as an argument and determines if there is an undirected path between pairs.
Suppose I have a list of edges (where G
is a graph):
isEdge(G,1,2). isEdge(G,2,3). isEdge(G,4,5).
So, because there is no edge between 3 and 4, this must fail.
How should I approach this problem? Should I go through each edge and write the edges in the list? or is there a better approach for this?
source to share
Solution 1: Using the library
It's easy if you use the graph theory library. First, I'll rewrite your graph using S-view:
[1-[2],2-[1,3],3-[2],4-[5],5-[4]]
Then I will use the library ugraph
included with SWI-Prolog ( thanks to Richard O'Keefe and Vitor Santos Costa ):
?- 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].
Solution 2: "Do it yourself"
Instead of relying on existing libraries, you can also implement this yourself in various ways (recommended if you want to be a better programmer!). One way to implement this form is to use clos0 / 3 , which implements reflexive-transitive closure on a binary predicate (generated by SO user false).
If you add matching edges to your database:
edge(1,2). edge(2,1). edge(2,3). edge(3,2). edge(4,5). edge(5,4).
... now you can request:
?- 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].
source to share
Assuming this is a follow-up to this question :
First, you need to define what it means to be connected:
connected_to(R_2, A,B) :-
( call(R_2, A,B)
; call(R_2, B,A)
).
Then you need to define a set of nodes. Usually a set of nodes is given, but it seems that you want them to be defined implicitly across all edges:
rel_nodes(R_2, Nodes) :-
setof(Node, Next^connected_to(R_2, Node,Next), Nodes).
Now connection means every node is connected to all other 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).
(All of this assumes that nodes are actually terrestrial members.)
Here are all the missing meta-predicate declarations:
:- meta_predicate connected_to(2,?,?), rel_nodes(2,?), is_connected(2).
source to share