【问题标题】:Coloring of a non-oriented planar graph in PrologProlog中无向平面图的着色
【发布时间】:2020-01-17 06:19:58
【问题描述】:

我有一个用 3 种颜色为图形着色的程序,相邻节点需要有不同的颜色。

我的问题是,它仅适用于有向图,当我使用无向图时,它会因堆栈溢出而失败。我知道有一些错误,你能帮忙吗 我让它适用于无向图?

最后那个findall/3也有问题。我需要将其更改为查找所有节点,不仅是带有edge(V,_) 的节点,但我不知道该怎么做。 我是初学者,我需要简单的解决方案。谢谢。

edge(1,2).
edge(2,3).
edge(2,4).
edge(3,4).

%for making the non-oriented graph I tried to use nonedge(X, Y) :- edge(X, Y).
%                                                 nonedge(X, Y) :- edge(Y, X).

color(blue).                                
color(red).
color(green).

coloring([V-C]) :-
   color(C),
   \+ edge(V,_).
coloring([V-C,V1-C1|Coloring]) :-
   color(C),
   edge(V, V1),
   V \== V1,
   coloring([V1-C1|Coloring]),
   C1 \== C.

colors(X) :-                      
   coloring(X),
   findall(V, edge(V,_), List),
   length(List, Len),
   length(X, Len).

【问题讨论】:

  • 我怀疑这不是有向图的工作版本?你能添加一个预期输入输出的例子吗?
  • 它正在工作,但不是 100% 正确。没有那个 oh(X, Y) :- h(X, Y). oh(X, Y) :- h(Y, X). 我有有向图,当我点击 `?- colors(X).` 我得到 X = [1-blue, 2-red, 3-blue, 4-red] 这是好的。我想让它也适用于两边的边缘,我需要更正findall 以显示所有节点,而不仅仅是带有边缘(V,_)的节点
  • 那么您的edge 谓词在哪里?应该改成oh还是少了点?
  • 抱歉,出现错误。现在更正了。这是一个工作版本。
  • 哦,这是来自stackoverflow.com/questions/10713690/…的复制粘贴

标签: prolog graph-theory graph-coloring


【解决方案1】:

在这个答案中,我们表示图形数据的方式与 OP 描述的方式不同。

相反,图是 Id-Neibs 对列表,Neibs 是相邻节点 Id 的列表,由类型检查谓词 is_graph/1 定义(显示在答案的末尾) .

为了给图表着色,我们使用:

:- use_module(library(clpfd)).

graph_coloring(G0, Zs) :-
   (  is_graph(G0)
   -> maplist(node_augmented_color, G0, G, Zs),
      maplist(agraph_coloring_outer(G), G)
   ;  throw(error(domain_error(graph,G0),_))
   ).

node_augmented_color(ID-Neibs, t(ID,Color,Neibs), Color).

agraph_coloring_outer(G, t(_,Color_v,Neibs_v)) :-
   maplist(agraph_coloring_inner(G,Color_v), Neibs_v).

agraph_coloring_inner(G, Color_x, Id_y) :-
   member(t(Id_y,Color_y,_), G),
   Color_x #\= Color_y.

使用 SWI-Prolog 8.0.0 的示例查询:

?- graph_coloring([1-[2],2-[1,3,4],3-[2,4],4-[2,3]], Zs),
   Zs ins 1..3,
   labeling([], Zs).
Zs = [1,2,1,3] ;
Zs = [1,2,3,1] ;
Zs = [1,3,1,2] ;
Zs = [1,3,2,1] ;
Zs = [2,1,2,3] ;
Zs = [2,1,3,2] ;
Zs = [2,3,1,2] ;
Zs = [2,3,2,1] ;
Zs = [3,1,2,3] ;
Zs = [3,1,3,2] ;
Zs = [3,2,1,3] ;
Zs = [3,2,3,1] ;
false.

要定义类型检查 is_graph/1(基于 iwhen/2distinct/1),请编写:

is_graph(G) :-
   iwhen(ground(G), is_graph_aux(G)).

is_graph_aux(G) :-
   maplist(pair_key, G, Nodes),
   distinct(Nodes),
   maplist(is_graph_aux_outer(G), G).

pair_key(K-_, K).

is_graph_aux_outer(G, E-Xs) :-
   distinct(Xs),
   maplist(is_graph_aux_inner(G,E), Xs).

is_graph_aux_inner(G, E, X) :-
   member(X-Ys, G),
   member(E, Ys).

【讨论】:

    【解决方案2】:

    代码也不适用于循环。它只检查前一个是否不相同。但在您的示例中,2 -> 3 -> 4 -> 2 -> .. 永远不会结束。

    此外,如果您的图表断开连接,它将永远不会返回整个图表。

    出于这两个原因,我建议采用完全不同的方法,首先找到所有唯一的顶点。然后为它们分配颜色并检查是否没有先前设置的颜色与设置的颜色冲突。

    colors(Colored) :-
            findall(U,edge(U,_),Vertices), 
            list_to_set(Vertices, UniqueVertices), %% find all unique vertices
            coloring(UniqueVertices,[], Colored). %% color them
    

    着色谓词如下所示:

    coloring([],Acc,Acc). %% base case for empty list
    coloring([H|T],Acc,AccRes) :-
        color(C), %% pick a valid color
        not((edge(H, V), member(V-C,Acc))), %% No linked vertex should have the same color
        coloring(T,[H-C|Acc],AccRes). %% Color the rest of the vertices
    

    此代码使用 accumulator 来保存先前设置的顶点颜色组合。

    【讨论】:

      猜你喜欢
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-28
      相关资源
      最近更新 更多