python-constraint添加约束

时间:2018-10-08 16:50:24

标签: python constraint-satisfaction

我正在开发一个python程序来解决约束满足问题(CSP)。

这里有变量列表 ['MI428','UL867','QR664','TK730','UL303'] 及其可能的赋值 ['A1','A2 ','B1','B2','C1']

我对此的限制是,在第二个列表中有每个元素的兼容性列表(可能的分配)。它的工作方式如下;

在第一个列表(变量列表)的元素中,还有另一个索引来获取另一个键。通过该键,我可以访问列表中的一组兼容值(可能的赋值)。为了更好地理解此示例:

  

对于变量'MI428',我有键'B320' ('MI428->'B320'),那么我有列表 B320 作为 ['A1','A2']

的兼容值

这里,我的任务是将 ['A1','A2','B1','B2','C1'] 的兼容值分配给每个变量,例如 MI428',满足上述约束。

注意:为此,我正在使用python-constraint库。我需要使用该实现。到目前为止,我立即创建了一个问题,如下所示,所以我真正想要的是对该问题添加约束。

from constraint import Problem
problem = Problem()
problem.addVariables(['MI428', 'UL867', 'QR664', 'TK730', 'UL303'], ['A1', 'A2', 'B1', 'B2', 'C1'])
problem.addConstraint() // I need this line to be implemented
solutions = problem.getSolutions()

对于addConstraint行,我需要适当的约束。

1 个答案:

答案 0 :(得分:0)

如果您不受约束库的约束,我强烈建议您使用SMT求解器。对于此类问题,它可以相对轻松地扩展到许多飞机/航班/机舱。此外,可以使用许多高级语言(包括Python)编写脚本。我建议针对此特定问题使用Microsoft的Z3。您可以从以下网址获得免费副本:https://github.com/Z3Prover/z3

虽然您可以通过多种方式对问题进行建模,但我认为以下是使用Z3的Python绑定对其进行编码的惯用方式:

from z3 import *

# Flights
Flight, (MI428, UL867, QR664, TK730, UL303) = EnumSort('Flight', ('MI428', 'UL867', 'QR664', 'TK730', 'UL303'))
flights = [MI428, UL867, QR664, TK730, UL303]

# Planes
Plane, (B320, B777, B235) = EnumSort('Plane', ('B320', 'B777', 'B235'))

# Bays
Bay, (A1, A2, B1, B2, C1) = EnumSort('Bay', ('A1', 'A2', 'B1', 'B2', 'C1'))
bays = [A1, A2, B1, B2, C1]

# Get a solver
s = Solver()

# Mapping flights to planes
plane = Function('plane', Flight, Plane)
s.add(plane(MI428) == B320)
s.add(plane(UL867) == B320)
s.add(plane(QR664) == B777)
s.add(plane(TK730) == B235)
s.add(plane(UL303) == B235)

# Bay constraints. Here're we're assuming a B320 can only land in A1 or A2,
# A B777 can only land on C1, and a B235 can land anywhere.
compatible = Function('compatible', Plane, Bay, BoolSort())

def mkCompat(p, bs):
    s.add(And([(compatible(p, b) if b in bs else Not(compatible(p, b))) for b in bays]))

mkCompat(B320, [A1, A2])
mkCompat(B777, [C1])
mkCompat(B235, bays)

# Allocation function
allocate = Function('allocate', Flight, Bay)
s.add(And([compatible(plane(f), allocate(f)) for f in flights]))
s.add(Distinct([allocate(f) for f in flights]))

# Get a model:
if s.check() == sat:
   m = s.model()
   print [(f, m.eval(allocate(f))) for f in flights]
else:
   print "Cannot find a satisfying assignment"

在计算机上运行它时,我得到:

$ python a.py
[(MI428, A1), (UL867, A2), (QR664, C1), (TK730, B2), (UL303, B1)]

这几乎不需要时间来计算,我相信它将毫无问题地扩展到数千个航班/飞机/海湾。 Z3是SMT求解器,您甚至可以以编程和简单的方式编写算术约束,例如到达/离开时间等。