我试图在 Prolog 中实现一些图形算法。我想出了一个想法,使用统一从图结构中构建一棵树:
该图将定义如下:
对的列表,
Vertex-Variable
其中Vertex
是表示顶点的常量,Variable
是对应的变量,将用作对顶点的“引用”。例如:[a-A, b-B, c-C, d-D]
对的列表
VertexVar-NeighboursList
,其中VertexVar
和 中的单个邻居NeighboursList
是“参考变量”。例如:[A-[B, C, D], B-[A, C], C-[A, B], D-[A]]
意思是b
,c
,d
是a
等的邻居。
然后在一些可以使用从原始图构建的某种树的图算法(如搜索组件,或简单的 DFS/BFS 等)之前,可以使用一些谓词,将这些对unify_neighbours
统一为. 之后,顶点变量可以被解释为它的邻居列表,其中每个邻居又是它的邻居列表。VertexVar-NeighbourList
VertexVar = NeighboursList
因此,这将在遍历图时产生良好的性能,因为不需要为图中的每个顶点线性搜索某些顶点及其邻居。
但我的问题是:如何比较那些顶点变量?(检查它们是否相同。)我尝试使用A == B
,但存在一些冲突。对于上面的示例,(使用unify_neighbours
谓词)Prolog 在内部将图形解释为:
[a-[S_1, S_2, S_3], b-S_1, c-S_2, d-S_3]
在哪里:
S_1 = [[S_1, S_2, S_3], S_2]
S_2 = [[S_1, S_2, S_3], S_1]
S_3 = [[S_1, S_2, S_3]]
问题在于S_1
and S_2
(又名b
and c
)X = [something, Y], Y = [something, X], X == Y
原样true
。同样的问题也会出现在共享相同邻居的顶点上。例如U-[A, B]
和V-[A, B]
。
所以我的问题是:有没有其他方法可以比较变量,可以帮助我解决这个问题?比较“变量本身”而不是内容的东西,比如比较过程编程语言中的地址?或者这是否过于程序化并破坏了 Prolog 的声明性思想?
例子
graph_component(Vertices, Neighbours, C) :-
% Vertices and Neighbours as explained above.
% C is some component found in the graph.
vertices_refs(Vertices, Refs),
% Refs are only the variables from the pairs.
unify_neighbours(Neighbours), % As explained above.
rec_(Vertices, Refs, [], C).
rec_(Vertices, Refs, Found, RFound) :-
% Vertices as before.
% Refs is a stack of the vertex variables to search.
% Found are the vertices found so far.
% RFound is the resulting component found.
[Ref|RRest] = Refs,
vertices_pair(Vertices, Vertex-Ref),
% Vertex is the corresponding Vertex for the Ref variable
not(member(Vertex, Found)),
% Go deep:
rec_(Vertices, Ref, [Vertex|Found], DFound),
list_revpush_result([Vertex|Found], DFound, Found1),
% Go wide:
rec_(Vertices, RRest, Found1, RFound).
rec_(Vertices, Refs, Found, []) :-
% End of reccursion.
[Ref|_] = Refs,
vertices_pair(Vertices, Vertex-Ref),
member(Vertex, Found).
这个例子并没有真正起作用,但它的想法。(另外,检查是否找到顶点是线性完成的,所以性能仍然不好,但这只是为了演示。)现在为变量找到对应顶点的谓词实现为:
vertices_pair([Vertex-Ref|_], Vertex-Ref).
vertices_pair([_-OtherRef|Rest], Vertex-Ref) :-
Ref \== OtherRef,
vertices_pair(Rest, Vertex-Ref).
\==
运营商并不是我真正想要的,它会产生这些冲突。