Prolog - 从邻接矩阵中提取边

时间:2015-01-18 21:02:11

标签: list graph prolog

我有一个列表列表,它代表图表的邻接矩阵 我正在寻找一种从中提取图形边缘的方法:

?- getEdges([[0,1,0,0],[1,0,1,1],[0,1,0,0],[0,1,0,0]],Edges).
Edges = [[1,2],[2,4],[2,3]]

THX

2 个答案:

答案 0 :(得分:0)

解决方案(假设有向图)有点像以下内容:

假设您正在检查邻接矩阵,并且您处于某一行。您需要一个谓词来检查此行的邻接列表并过滤掉所有0 - 元素,从而生成包含以下格式元素的列表:

(From, To)

其中From对应于行索引,To对应于非零列。 执行此操作的简单谓词将被称为

?- rowEdges(Row, AdjList, Result).

所以你可以尝试这样做:

rowEdges(Row, AdjList, Result) :- edges(AdjList, 1, Row, [], Result).

edges([H|T], Column, Row, Acc, Res) :-
    NewColumn is Column + 1,
    ( H =:= 1 -> edges(T, NewColumn, Row, [(Row, Column)|Acc], Res);
      edges(T, NewColumn, Row, Acc, Res)).
edges([], _, _, Res, Res).

谓词edges/5检查行的邻接列表中的每个元素,同时跟踪元素的列索引。如果应该添加边缘,那么它将采用(Row, Column)形式,这就是我们必须提供Row作为参数的原因。

rowEdges/3只提供正确的初始化,它应该是累加器(Acc)的空列表,以及列索引的1。 现在,您只需rowEdges/3并将其应用于您必须通过类似过程找到所有边缘的每一行。

示例:

?- rowEdges(2, [1,0,1,1,0,1], Result).
Result = [(2, 6), (2, 4), (2, 3), (2, 1)].

如果您希望以升序列顺序生成边缘,则只需修改rowEdges/3以生成反向输出,因为edges/5正在使用累加器。

rowEdges(Row, AdjList, Result) :- edges(AdjList, 1, Row, Acc, Res), reverse(Res, Result).

答案 1 :(得分:0)

另一种方法是,首先创建一个标识有效边的谓词。对于无向图,这是一个简单的谓词:

edge(M, [R,C]) :-
    nth1(R, M, Row),
    nth1(C, Row, 1),
    R =< C.               % Remove this for directed graphs

以下是一个示例查询:

| ?- edge([[0,1,0,0],[1,0,1,1],[0,1,0,0],[0,1,0,0]],Edge).

Edge = [1,2] ? a

Edge = [2,3]

Edge = [2,4]

(1 ms) no
| ?-

它识别每个回溯的每个边缘。它使用了nth1/3谓词,这是nth1(N, List, Element)的关系, Element位于N 中的位置List ,其中第一个元素是元素编号1

对于有向图,只需删除R =< C条件,然后您就可以获得:

| ?- edge([[0,1,0,0],[1,0,1,1],[0,1,0,0],[0,1,0,0]],Edge).

Edge = [1,2] ? a

Edge = [2,1]

Edge = [2,3]

Edge = [2,4]

Edge = [3,2]

Edge = [4,2]

(1 ms) no
| ?-

如果您想要另一种方式来表示边缘而不是2个元素列表[R,C],则只需将子句的头部从edge(M, [R,C])更改为edge(M, R-C)

| ?- edge([[0,1,0,0],[1,0,1,1],[0,1,0,0],[0,1,0,0]],Edge).

Edge = 1-2 ? a

Edge = 2-3

Edge = 2-4

(1 ms) no
| ?-

如果您想将所有边缘收集到一个列表中,可以使用setof/3

all_edges(M, Edges) :-
    setof(E, edge(M, E), Edges).

| ?- all_edges([[0,1,0,0],[1,0,1,1],[0,1,0,0],[0,1,0,0]],E), Edges).

Edges = [1-2,2-3,2-4]

yes
| ?-