跳转至
1.2.1

建模指南

用 OptModel 同时管理决策变量、派生表达式、约束和目标。所有参与同一个表达式的节点必须属于同一个模型。

数值变量与约束

from optagent import OptModel

model = OptModel()
x = model.int(0, 10)
y = model.int(0, 10)
cost = 2 * x + y
model.constraint(x + y >= 7)
model.minimize(cost)

int() 和 float() 的上下界包含端点;省略边界表示未声明该边界。建议提供业务上有效的边界,尤其是需要有限域转换的模型。default 是初始值,不是固定变量的约束;省略时由内核构造初始候选。

表达式不是 Python 布尔值

使用 &、|、~ 或 model.and_()、model.or_() 组合条件;两侧比较表达式加括号。不要使用 Python 的 and、or、if expression 或链式比较来构造约束。条件表达式使用 model.iif(condition, when_true, when_false)。

集合与序列

set(n) 和 list(n) 的成员来自 0 到 n - 1,每个成员最多出现一次。集合不关心顺序;序列保留顺序。list(n) 不自动要求包含所有成员,完整排列需要显式约束长度。

from optagent import OptModel

model = OptModel()
team_a = model.set(6)
team_b = model.set(6)
model.constraint(model.partition(team_a, team_b))
model.constraint(team_a.count() >= 2)
model.minimize(team_a.count())

上述划分约束保证编号 0 到 5 恰好分给一组;第一组至少有 2 个成员,最小化人数会让它选取 2 个成员,其余 4 个归第二组。partition() 本身只生成布尔表达式,外层 constraint() 才把它加入模型。

三种关系都要求输入为同类、同全集的决策变量:partition() 要求每项恰好归属一组;disjoint() 要求最多归属一组,允许遗漏;cover() 要求至少归属一组,允许跨组重复。序列变量也能参与这些关系,但关系不限制组内顺序。

union() 和 intersection() 则生成并集与交集的集合值,可继续计数或判断成员。例如 model.count(model.intersection(a, b)) == 0 表达没有公共成员,还需传给 constraint() 才成为约束。

各接口的参数限制与可运行示例见 set、list、partition、disjoint、cover、union 和 intersection。

区间与可选任务

区间的边界是最早开始和最晚结束,持续时间需要通过 length() 或 .length 单独约束。必选区间允许零长度;可选区间可缺席。

from optagent import OptModel

model = OptModel()
a = model.interval(0, 20)
b = model.interval(0, 20)
model.constraint(a.length == 3)
model.constraint(b.length == 5)
model.constraint(a.end <= b.start)
model.minimize(b.end)

用 optional_interval() 表达可不执行的任务,通过 presence() 约束出现条件。业务所需的时长、先后关系和资源约束仍需显式建模。

数组与 Lambda

array() 构造常量或表达式数组,at() 支持表达式索引;range() 与 lambda_function() 用于迭代和映射。Python 的列表是建模时的容器,模型的数组表达式参与求解时的计算。

from optagent import OptModel

model = OptModel()
choice = model.int(0, 2)
costs = model.array([8, 3, 5])
model.minimize(costs[choice])

动态索引应有明确范围。需要默认值的数组访问可使用 expression.at(index, default=value);具体形状与类型要求见 API 参考。

多目标与模型生命周期

多次调用 minimize() / maximize() 按声明顺序形成字典序目标。先比较第一个目标,相同后再比较后续目标;这不是加权求和。

完成全部建模后再求解。创建新表达式、变量或修改约束、目标会使模型上的旧值失效;需要重新求解后再读取 .value。在求解前保存好希望读取的派生表达式。

查阅建模 API →