cp_optimizer入门引言和资料
CP Optimizer 是一个软件库,提供了用于对约束规划问题进行建模和求解的构造。
在 CP Optimizer 之前,有 ILOG Solver 和 ILOG Scheduler。调度问题由调度程序中的“活动”建模,活动由几个整数变量组成。Scheduler 取得了成功,但越来越难跟上客户的需求。工业问题通常包含某种替代方案、替代资源、可选目标等。很难使用活动对它们进行建模(例如,未执行活动的长度是多少?)。解决这些模型也很困难。
参考
# 示例代码
https://github.com/IBMDecisionOptimization/docplex-examples
# 函数说明
https://ibmdecisionoptimization.github.io/docplex-doc/cp/docplex.cp.modeler.py.html#scheduling-functions
整数变量与约束
from docplex.cp.model import CpoModel
mdl = CpoModel()
Belgium = mdl.integer_var(0, 3, "Belgium")
Denmark = mdl.integer_var(0, 3, "Denmark")
mdl.add(Belgium != France) # 增加约束Belgium和France颜色不一样
msol = mdl.solve(TimeLimit=10) # 求解
integer_var_list与element
nametuple
from collections import namedtuple
Warehouse = namedtuple('Wharehouse', ('city','capacity','cost')) # Name of the city
WAREHOUSES = (Warehouse("Bonn", 3, 480),
Warehouse("Bordeaux", 1, 200),
Warehouse("London", 2, 320),
Warehouse("Paris", 4, 340),
Warehouse("Rome", 1, 300))
integer_var_list
# Create one variable per store to contain the index of its supplying warehouse
NB_WAREHOUSES = len(WAREHOUSES)
'''
决策变量, store对应warehouse的编号
NB_STORES 决策变量的数量
0 最小值
NB_WAREHOUSES - 1 最大值
"supplier" 名称
'''
supplier = mdl.integer_var_list(NB_STORES, 0, NB_WAREHOUSES - 1, "supplier")
'''
决策变量, warehouse是否开放
'''
open_var = mdl.integer_var_list(NB_WAREHOUSES, 0, 1, "open")
element
for s in supplier:
# 相当于open_var[s]==1, supplier中存在的warehouse必须打开
mdl.add(mdl.element(open_var, s) == 1)
#### 计算内积(scalar product)
total_cost = mdl.scal_prod(open_var, [w.cost for w in WAREHOUSES])
注意,element函数里面不区分参数的次序。
for sx in range(NB_STORES):
total_cost = total_cost + mdl.element(supplier[sx], SUPPLY_COST[sx])
'''
mdl.element(supplier[sx], SUPPLY_COST[sx]) = SUPPLY_COST[sx][supplier[sx]]
sx: store的index
supplier[sx]: supplier的index
'''
golomb_ruler问题与all_diff
mdl = CpoModel()
ORDER = 6
MAX_LENGTH = (ORDER - 1) ** 2
marks = mdl.integer_var_list(ORDER, 0, MAX_LENGTH, "M") # 标记点的整数决策变量
dist = [marks[i] - marks[j] for i in range(1, ORDER) for j in range(0, i)]
mdl.add(mdl.all_diff(dist)) # 任意两点的差不能一样
mdl.add(marks[0] == 0) # 第一个标记点为0
for i in range(1, ORDER): # 保证间隔越来越大,防止同类型解
mdl.add(marks[i] > marks[i - 1])
# 防止镜像解
mdl.add((marks[1] - marks[0]) < (marks[ORDER - 1] - marks[ORDER - 2]))
# 最小化标记点
mdl.add(mdl.minimize(marks[ORDER - 1]))