我有一个计算问题,我有一组标签,可以给出一次,以及一些项目,每个项目都有一组可以接受的标签选择。我需要以这样的方式分配标签:每当有问题的解决方案时,每个项都会得到一个标签。
举一个具体的例子,如果我有这样的字典:
options = {
'a': [1],
'b': [2, 3],
'c': [1, 2]
}
..然后解决方案是:
{'a': 1, 'b': 3, 'c': 2}
我还需要能够扩展问题以处理多个约束,例如
[1], ['A', 'B'] # -> (1, A) or (1, B)
[1, 2, 3], ['A', 'C'] # -> (3, C)
[1, 2], ['A', 'C'] # -> (2, A) or (2, B)
我试图为简单的情况提出基于优先级队列的可行解决方案,但是这完全由于多个约束而崩溃。我可以使用itertools.permutations
来强制解决方案,但我更喜欢有效的实现。是否有任何已知的算法可能适用于此问题?
答案 0 :(得分:1)
我会使用回溯来解决这个问题。 根据贪婪算法可以实现的约束,一次选择1个标签以实现全局最优
答案 1 :(得分:1)
在形式上,你在示例中所拥有的是一个简单的约束满足问题,它有三个变量['a', 'b', 'c']
,每个变量都有一个有限的整数域和" all-distinct"约束
使用适当的启发式方法进行回溯搜索可以在实践中相当快地解决此类问题。 E.g。
def backtracking(domains):
if any(len(dom) == 0 for var, dom in domains.iteritems()):
return None
if all(len(dom) == 1 for var, dom in domains.iteritems()):
return domains
# minimum remaining values heuristic: process variables with few possible
# values first (fail-first strategy)
order = sorted(domains.iteritems(), key=lambda (var, dom): len(dom))
for var, dom in order:
if len(dom) == 1:
continue
for value in list(dom):
doms = {v: d - {value} for v, d in domains.iteritems()
if v != var}
doms[var] = {value}
solution = backtracking(doms)
if solution is not None:
return solution
print(backtracking({v: set(d) for v, d in options.iteritems()}))
答案 2 :(得分:1)
您不必为了解决此问题而实施整个回溯系统。许多研究人员已经构建了系统和建模语言来促进这种问题的解决。
你的问题是一个非常经典的约束满足问题,我们有AllDifferent Constraint。我建议你使用像minizinc(http://www.minizinc.org/)这样的高级建模语言,你会亲眼看到它的不同之处。这是一个以这种格式编写的简单模型(针对您的问题):
include "globals.mzn";
var {1} : a;
var {2,3} : b;
var {1,2} : c;
constraint alldifferent([a,b,c]);
solve satisfy;
output ["a : ", show(a), "\n" ,
"b : ", show(b), "\n" ,
"c : ", show(c), "\n" ];
如果这是您第一次使用minizinc,则可以从最新的教程here开始。
答案 3 :(得分:0)
这是一个非常基本的AllDifferent Constraint。如果对python感兴趣,请使用 https://pypi.python.org/pypi/python-constraint
problem = Problem()
problem.addVariable("a", [1, 2])
problem.addVariable( "b", [2, 3])
problem.addVariable("c", [1, 2])
problem.addConstraint(AllDifferentConstraint())
print problem.getSolution()
(如果存在,会给你第一个找到的 或
print sorted(sorted(x.items()) for x in problem.getSolutions())
将提供所有解决方案)