从Prolog中的图形创建节点列表?

时间:2014-05-08 05:17:33

标签: list recursion graph prolog

我试图使用图表中边缘的信息。我想从图中的边缘创建一个节点列表。例如:

? - graph([edge(1,2),edge(2,3),edge(3,4)],List).
List = [1,2,3,4]

这是一个基本案例:

graph([edge(X,Y)],[X,Y]).

我不知道怎么做,没有知识库。为什么这不仅仅是自己的工作?或类似的东西?

graph([edge(X,Y)], List) :- append(X,Y,List).

我对Prolog很新,并希望得到帮助。

3 个答案:

答案 0 :(得分:1)

without a knowledge base是一个奇怪的陈述。如果你有一些edge / 2,你可以使用snippet轻松收集所有节点标识符:

nodes(Ns) :- setof(N, M^(edge(N, M) ; edge(M, N)), Ns).

编辑根据评论中的代码,我建议

nodes_of_graph(graph(Edges), Ns) :-
  setof(N, M^(member(edge(N, M), Edges) ; member(edge(M, N), Edges)), Ns).

产量

1 ?- nodes_of_graph(graph([edge(1,2),edge(1,3)]),L).
L = [1, 2, 3].

答案 1 :(得分:1)

这是一个仅使用基本Prolog的解决方案: 我认为基本情况应该是空图,而不是只有一个元素的图。它没有节点:

nodes([],[]).

对于每个非空图,您收集第一条边的两个节点,然后继续图的其余部分:

nodes([edge(X,Y)|RestGraph],[X,Y|RestNodes]) :-
  nodes(RestGraph,RestNodes).

此解决方案的问题在于结果中可能有多次节点。您可以使用sort / 2消除此类重复:

nodes2(Graph,Nodes) :- nodes(Graph,Unsorted), sort(Unsorted,Nodes).

CapelliC的解决方案更加优雅和简洁,但对初学者来说可能更难理解。

答案 2 :(得分:1)

通过使用member/2目标的辅助谓词来避免对setof/3的双重调用的性能损失,可以改进Carlo的解决方案。例如:

nodes_of_graph(graph(Edges), Nodes) :-
    setof(Node, edge_node(Edges, Node), Nodes).

edge_node(Edges, Node) :-
    member(edge(Begin, End), Edges),
    (   Node = Begin
    ;   Node = End
    ).

这种替代方案还提高了可读性(但是以增加一个辅助谓词为代价)。