问题描述:用 4 色给一个地图上色,要求相邻的区域不能上相同的颜色。区域不存在飞地之类的。
用建模语言来描述,是这样的:
我觉得也可以用图模型来表示。
可能的优化思路:先决定那些具有更多相关约束的区域,这能通过对称性或者帮助优化剪枝降低搜索规模。
一种实现是 Constraint Programming System,也就是将所有的约束记录在一张大表格中,并在搜索的过程中追踪这些约束的激活情况,以此来剪掉不可行的分支。
比如下面是为 color[Belgium] 指配了 black 后的所有条件。
还有一种实现是,我们可以将相邻约束问题转化为为每一个区域追踪一个「还能选择的颜色」的列表,如果有一个待定区域没有可选颜色了就说明不可行;如果有且仅有一种颜色就是必走的路径。
考虑到每个行有且仅有一个皇后,变量表示第 $i$ 行($i \in [1..8]$)的皇后在第 $x_i$ 列,$x_i \in [1..8]$。
这样要考虑的约束就是各列有没有碰撞、各个对角线有没有碰撞。
这样的模型可以编写为:
range R = 1..8;
var{int} x[R] in R;
solve {
forall (i in R, j in R: i < j) {
x[i] \\neq x[j];
x[i] \\neq x[j] - (j-i);
x[i] \\neq x[j] + (j-i);
}
}
这是一个来自某个 CPS 库 https://pypi.org/project/python-constraint/ 的例子。
>>> from constraint import * >>> problem = Problem() >>> problem.addVariable("a", [1,2,3]) >>> problem.addVariable("b", [4,5,6]) >>> problem.getSolutions() [{'a': 3, 'b': 6}, {'a': 3, 'b': 5}, {'a': 3, 'b': 4}, {'a': 2, 'b': 6}, {'a': 2, 'b': 5}, {'a': 2, 'b': 4}, {'a': 1, 'b': 6}, {'a': 1, 'b': 5}, {'a': 1, 'b': 4}] >>> problem.addConstraint(lambda a, b: a*2 == b, ("a", "b")) >>> problem.getSolutions() [{'a': 3, 'b': 6}, {'a': 2, 'b': 4}] >>> problem = Problem() >>> problem.addVariables(["a", "b"], [1, 2, 3]) >>> problem.addConstraint(AllDifferentConstraint()) >>> problem.getSolutions() [{'a': 3, 'b': 2}, {'a': 3, 'b': 1}, {'a': 2, 'b': 3}, {'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3}]