Prolog中的四色定理(使用动态谓词)

时间:2010-06-13 14:36:35

标签: dynamic map colors prolog

我正在使用SWI-Prolog根据四色定理(http://en.wikipedia.org/wiki/Four_color_theorem)着色地图。到目前为止,我的程序看起来像这样:

colour(red).
colour(blue).

map_color(A,B,C) :- colour(A),
         colour(B),
         colour(C),
         C \= B,
         C \= A.

(实际的程序会更复杂,有4种颜色和更多的字段,但我想我会从一个简单的案例开始)

现在,我想避免使用具有相同结构的双重解决方案。例如。对于具有三个字段的地图,解决方案“红色,红色,蓝色”将具有与“蓝色,蓝色,红色”相同的结构,仅具有不同的颜色名称,并且我不希望它们都显示。

所以我想我会有一个动态谓词解决方案/ 3,并在我的map_color谓词的末尾调用assert(解决方案(A,B,C))。然后,对于每个解决方案,检查它们是否已作为解决方案/ 3事实存在。问题是我必须断言像解决方案(Color1,Color1,Color2),即使用变量来进行统一检查。我无法想到实现这一目标的方法。

所以,问题是,断言找到解决方案然后进行统一测试的最佳方法是什么,以便“红色,红色,蓝色”与“蓝色,蓝色,红色”统一?

2 个答案:

答案 0 :(得分:1)

建立变量之间的关系:

mask_helper(_, _, [], []).
mask_helper(A, B, [A|_], [B|_]):- !.
mask_helper(A, B, [X|Xs], [_|Ys]):-
    A \= X,
    mask_helper(A, B, Xs, Ys).

mask([], []).
mask([X|Xs], [Y|Ys]):-
    mask_helper(X,Y,Xs,Ys),
    mask(Xs, Ys).

你可以建立你的面具:

?- mask([red,red,blue],X).
X = [_G300, _G300, _G306] .

但:

?- mask([red,red,blue],X), mask([blue,red,red],Y), X=Y.
X = [_G27, _G27, _G27],
Y = [_G27, _G27, _G27].

即。如果您使用Color1 \= Color2(没有规则正文),则assert没有关系。

您可能会考虑分配颜色的顺序(非常流行的方法):

colour(red). colour(green). colour(blue).

colour_order(red, red).
colour_order(red, green).
colour_order(red, blue).
colour_order(green, green).
colour_order(green, blue).

colour_code([]).
colour_code([X]):- colour(X).
colour_code([X|[Y|T]]):-
    colour_order(X,Y),
    colour_code([Y|T]).

map_color(A,B,C):-
    colour_code([A,B,C]),
    C \= B, C \= A.

但如果您的条件为A \= B, B \= C,您将永远不会得到“红色,蓝色,红色”的结果。

想一想:

unify([], [], _).
unify([X|Xs], [Y|Ys], M):-
    member((X=Z), M), !,
    Z = Y,
    unify(Xs, Ys, M).

unify([X|Xs], [Y|Ys], M):-
    % X is not assigned yet
    not(member((_=Y),M)), % Y is not used as well
    unify(Xs, Ys, [(X=Y)|M]).

比你可以比较:

?- unify([red,red,blue],[blue,blue,red],[]).
true.

?- unify([red,red,blue],[blue,blue,blue],[]).
false.

?- unify([red,red,blue],[blue,red,red],[]).
false.

答案 1 :(得分:0)

我认为最简单的解决方案是说A总是红色(例如)。