如何 - Prolog中的图形着色

时间:2012-05-23 04:58:59

标签: graph colors prolog graph-coloring

我正在尝试在Prolog中制作简单的图形着色算法,但我在理解语言时遇到了一些困难。我知道我想做什么 - 我想去一个顶点,找到连接到它的所有其他顶点,检查我的顶点的颜色,并根据它,用不同的颜色着色其他顶点。我只是很难将其翻译成Prolog。如果它是C语言或Java语言,对我来说这将是一块蛋糕,但这给了我适合。

这是我到目前为止所做的:

main:- graph_coloring.

%color_list([blue, red, green, yellow, white], colors).
%vertex_list([a, b, c, d], vertices).
%edge_list([(a,b),(b,c),(c,d)], edges).

%Our graph
color(blue).
color(red).
color(green).
color(black).
color(white).

%graph([a-b, b-c, b-d, c-d]).

vertex(a).
vertex(b).
vertex(c).
vertex(d).

%Subject to changing, so are asserted into listener at runtime.
init_dynamic_facts:-
    assertz(vertex_color(a, none)),
    assertz(vertex_color(b, none)),
    assertz(vertex_color(c, none)),
    assertz(vertex_color(d, none)),
    assertz(location(a)).

edge(a,b).
edge(b,c).
edge(b,d).
edge(c,d).

is_connect(A,B):-
    edge(A,B).
is_connect(A,B):-
    edge(B,A).

connections(Vertex):-
    edge(Vertex,X).
connections(Vertex):-
    edge(X,Vertex).

move(Vertex):-
    retract(location(_)),
    asserta(location(Vertex)).

paint_vertex(Vertex, Color):-
    retract(vertex_color(Vertex,_)),
    asserta(vertex_color(Vertex, Color)).

find_vertex_color(Vertex):-
    vertex_color(Vertex, X).


graph_coloring:-

    location(Current_vertex),
    vertex_color(Current_vertex, Curr_color),
    ( Curr_color =:= none ->
        connections(Current_vertex, Others),
        vertex_color(Others, Other_colors),
        paint_vertex(Current_vertex, 

如何完成此算法?

(已编辑:graph_coloring下的更多代码)

2 个答案:

答案 0 :(得分:2)

我认为你试图以一种对Prolog程序来说不自然的方式思考;也就是说,你尽量不使用递归:)我已经想出了如下,然而这可能不完全正确(这是晚了,我没有试图想在像时候了良好的口碑这...... :))

我们假设你有以下事实描述的图表:

edge(a,b).
edge(b,c).
edge(b,d).
edge(c,d).

并且可用的颜色是

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

(你只需要3种颜色来为平面图形着色,所以我们在这里使用3)。我们还假设您希望将答案作为[顶点颜色]列表给出,其中列表将包含图表每个顶点的颜色。我相信以下是一个正确的解决方案:

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.

第一个条款说如果从V到任何其他顶点没有边缘,只需尝试所有可能的颜色。第二条说,顶点V将得到颜色C和顶点V1将得到肤色C1如果从V到V1,边缘其中V!= V1和C!= C1。 (我还假设你的图是连通的,即没有没有连接到其他顶点的顶点)。

由于我们只想解决方案,所有的顶点具有的颜色,我们将只保留长的名单| V |,其中V是集你有顶点。您可以通过各种方式实施此限制;我更喜欢使用“findall / 3”:

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

现在,通过咨询此程序并询问|?- colors(X).,您将获得图表顶点的所有可能颜色分配。

如果有人发现问题,我几乎可以肯定上述解决方案中存在,请告诉我们:)

施皮罗斯

答案 1 :(得分:1)

我想提一下这个问题是一个典型的约束满足问题,并且可以使用 SWI-Prolog 的CSP模块来提高效率。这是完整的算法:

color/1

vertex/1表示可用的颜色,edge/2表示图表中的顶点,colorGraph(?List)表示顶点之间的耦合。此外,List确定顶点的颜色,其中hasColor(Vertex, Color)Vertex子句的列表,Color是使用:- use_module(library(clpfd)). 的彩色顶点。

让我们详细介绍上述算法的每个部分,以了解会发生什么。

colorGraph(ColorList) :- 
  findall((X, Y), edge(X, Y), Edges),
  findall(X, vertex(X), Vertexes),
  findall(hasColor(X, _), member(X, Vertexes), ColorList),
  createConstraint(Edges,ColorList),
  colorNodes(ColorList).

它指示 SWI-Prolog 加载包含约束满足问题的谓词的模块。

colorGraph/1

谓词ColorList是算法的入口点。它将边/顶点的子句转换为列表,约束createConstraint([],_). createConstraint([(V1,V2)|RL],ColorList):- member(hasColor(V1,C1),ColorList), member(hasColor(V2,C2),ColorList), dif(C1,C2), createConstraint(RL,ColorList). 以定义顶点列表,最后创建颜色约束并分配颜色(它们是两个独立的操作)。

createConstraint/2

预测dif/2只是说明两个链接的顶点必须具有不同的颜色。值得一提的是colorNodes([]). colorNodes([hasColor(_,C)|Nodes]) :- color(C), colorNodes(Nodes). 是一个CSP谓词。

colorNodes/1

谓词colorGraph/1为顶点指定正确的颜色。 Prolog将根据上面定义的约束来分配正确的颜色。

最后,通过调用谓词?- colorGraph(L). L = [hasColor(a, red), hasColor(b, blue), hasColor(c, green), hasColor(d, red), hasColor(e, red)] ; L = [hasColor(a, red), hasColor(b, blue), hasColor(c, green), hasColor(d, red), hasColor(e, blue)] ; L = [hasColor(a, red), hasColor(b, blue), hasColor(c, green), hasColor(d, red), hasColor(e, green)] ; L = [hasColor(a, red), hasColor(b, green), hasColor(c, blue), hasColor(d, red), hasColor(e, red)] ; L = [hasColor(a, red), hasColor(b, green), hasColor(c, blue), hasColor(d, red), hasColor(e, blue)] ; L = [hasColor(a, red), hasColor(b, green), hasColor(c, blue), hasColor(d, red), hasColor(e, green)] ; L = [hasColor(a, blue), hasColor(b, red), hasColor(c, green), hasColor(d, blue), hasColor(e, red)] ; L = [hasColor(a, blue), hasColor(b, red), hasColor(c, green), hasColor(d, blue), hasColor(e, blue)] ; L = [hasColor(a, blue), hasColor(b, red), hasColor(c, green), hasColor(d, blue), hasColor(e, green)] ; L = [hasColor(a, blue), hasColor(b, green), hasColor(c, red), hasColor(d, blue), hasColor(e, red)] ; L = [hasColor(a, blue), hasColor(b, green), hasColor(c, red), hasColor(d, blue), hasColor(e, blue)] ; L = [hasColor(a, blue), hasColor(b, green), hasColor(c, red), hasColor(d, blue), hasColor(e, green)] ; L = [hasColor(a, green), hasColor(b, red), hasColor(c, blue), hasColor(d, green), hasColor(e, red)] ; L = [hasColor(a, green), hasColor(b, red), hasColor(c, blue), hasColor(d, green), hasColor(e, blue)] ; L = [hasColor(a, green), hasColor(b, red), hasColor(c, blue), hasColor(d, green), hasColor(e, green)] ; L = [hasColor(a, green), hasColor(b, blue), hasColor(c, red), hasColor(d, green), hasColor(e, red)] ; L = [hasColor(a, green), hasColor(b, blue), hasColor(c, red), hasColor(d, green), hasColor(e, blue)] ; L = [hasColor(a, green), hasColor(b, blue), hasColor(c, red), hasColor(d, green), hasColor(e, green)] ; 可以找到结果,例如:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World");
            Console.ReadLine();
        }
    }
}