【发布时间】:2019-04-02 10:04:56
【问题描述】:
我试图在 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 和S_2(又名b 和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).
\== 运算符并不是我真正想要的,它会产生这些冲突。
【问题讨论】:
-
我不完全理解你的想法......也许你错过了变量是 local 的子句?
-
我会添加一个例子。
-
为顶点提供的变量是子句中的局部变量,用于处理图形搜索。
标签: reference prolog logic-programming declarative-programming