跳转至

Builder API

ModelBuilder 是公开建模入口。教程式说明见 建模接口

本页标题只显示方法名,便于右侧目录快速定位。每个方法下面给出签名、参数、返回值和带注释示例。

Exact Solver Compatibility

ModelBuilder 是统一建模入口,但精确解后端不是通用解释器。CP-SAT 和 MILP 只接收各自可降阶的 DAG 子集;如果模型包含某个后端不支持的接口,需要改用启发式、混合策略,或调整建模形式。

按后端查看支持清单,见 精确求解器接口兼容性

标签含义:

标签 含义
HEURISTIC 启发式路径可评估或搜索该接口表达的模型语义。
CP-SAT 当前 CP-SAT 精确路径可 lowering 到 cp_sat_native
MILP 当前 MILP 精确路径可 lowering 到 mathopt_mp / highs_native
MODEL 建模、登记或导出接口;不直接代表求解语义。

精确解支持矩阵:

接口 标签 CP-SAT MILP 说明
const HEURISTIC CP-SAT MILP 支持整数/布尔常量 支持数值/布尔常量 CP-SAT 要求参与精确解的常量为整数或布尔值。
bool_var HEURISTIC CP-SAT MILP 支持 支持 MILP 会降为 0/1 变量。
int_var HEURISTIC CP-SAT MILP 支持有界整数 支持 CP-SAT 要求有限 lb / ub
float_var HEURISTIC MILP 不支持 支持 CP-SAT 当前只构建整数域精确模型。
set_var HEURISTIC 不支持 不支持 当前 exact canonical model 没有集合变量表示。
sequence_var HEURISTIC CP-SAT 仅通过 no_overlap 绑定 interval 后支持 不支持 CP-SAT 用 rank 变量表达序列;单独序列或黑盒路线不属于 exact 支持面。
interval_var HEURISTIC CP-SAT 支持 不支持 MILP 当前只做线性 MP lowering,不接收 interval 结构。
abs HEURISTIC CP-SAT 支持 不支持 MILP 当前未线性化绝对值,需要用户手动改写为线性约束。
sum HEURISTIC CP-SAT MILP 支持 支持线性求和 MILP 要求所有输入保持线性。
min / max HEURISTIC CP-SAT 支持 不支持 MILP 当前未自动引入辅助变量和 epigraph 约束。
and_ / or_ / not_ HEURISTIC CP-SAT 支持布尔表达式 不支持 MILP 当前不做逻辑重写或 big-M 线性化。
iif HEURISTIC 不支持 不支持 两个 exact 路径都未实现条件表达式 lowering。
set_len / set_contains HEURISTIC 不支持 不支持 依赖集合变量,当前 exact canonical model 不包含集合语义。
sequence_contains HEURISTIC 不支持 不支持 CP-SAT 当前 sequence 支持仅限 no_overlap 绑定的排序语义。
all_different HEURISTIC CP-SAT 支持 不支持 MILP 当前不自动构造 pairwise 或 assignment 线性化。
element / table HEURISTIC 不支持 不支持 当前 exact backend 没有 element/table 原生或线性化实现。
interval_start / interval_end / interval_length HEURISTIC CP-SAT 支持 不支持 只在 CP-SAT interval 模型中可用。
cumulative / no_overlap / precedence HEURISTIC CP-SAT 支持 不支持 调度约束当前走 CP-SAT;MILP 不做调度结构线性化。
external_call HEURISTIC 不支持 不支持 精确解后端不能调用任意 Python 黑盒函数并证明全局最优。
constraint / minimize / maximize MODEL 取决于内部表达式 取决于内部表达式 登记接口本身可用,精确解兼容性由包裹的表达式决定。
to_program_spec / freeze MODEL 可用 可用 输出模型结构;不改变 solver 支持范围。

不能只按变量类型选择精确解

即使模型用了 int_var,只要目标或约束里包含 external_calliifelement、集合接口,当前精确解路径仍会拒绝 lowering。选择 CP-SAT 或 MILP 时,以完整表达式图是否兼容为准。

接口分组

分组 方法
常量与变量 constbool_varint_varfloat_varset_varsequence_varinterval_var
数值与逻辑表达式 abssumminmaxand_or_not_iif
集合与序列 set_lenset_containssequence_containsall_differentelementtable
调度 interval_startinterval_endinterval_lengthcumulativeno_overlapprecedence
黑盒 external_call
登记 constraintminimizemaximize
输出 to_program_specfreeze

const

标签HEURISTIC CP-SAT MILP

签名const(value: bool | int | float | list[int] | dict[str, int]) -> Expr

参数 类型 含义
value bool | int | float | list[int] | dict[str, int] 要接入表达式图的常量值。

返回值Expr,常量表达式节点。

# 1. 把业务中的固定罚分转成 builder 表达式。
penalty = builder.const(10)

# 2. 常量表达式可以和变量表达式一起构造约束。
builder.constraint(x + penalty <= 20, name="budget")

bool_var

标签HEURISTIC CP-SAT MILP

签名bool_var(default: bool = False, *, name: str | None = None) -> Expr

参数 类型 含义
default bool 初始布尔值,默认 False
name str | None 变量名,用于输出、trace 和调试。

返回值Expr,布尔决策变量。

# 1. 创建一个是否选择某个方案的 0/1 决策。
pick = builder.bool_var(default=False, name="pick_item")

# 2. 把业务规则登记成正式约束。
builder.constraint(pick == 1, name="must_pick")

int_var

标签HEURISTIC CP-SAT MILP

签名int_var(default: int = 0, *, lb: int | None = None, ub: int | None = None, name: str | None = None) -> Expr

CP-SAT 边界

CP-SAT 精确路径要求整数变量有有限 lb / ub。如果省略边界,建模仍然有效,但 CP-SAT lowering 会拒绝该模型。

参数 类型 含义
default int 初始整数值。
lb int | None 下界,None 表示不显式设置。
ub int | None 上界,None 表示不显式设置。
name str | None 变量名。

返回值Expr,整数决策变量。

# 1. 建立一个范围为 [0, 10] 的整数变量。
quantity = builder.int_var(default=0, lb=0, ub=10, name="quantity")

# 2. 在后续表达式里使用该变量。
builder.constraint(quantity <= 6, name="stock_limit")

float_var

标签HEURISTIC MILP

签名float_var(default: float = 0.0, *, lb: float | None = None, ub: float | None = None, name: str | None = None) -> Expr

参数 类型 含义
default float 初始连续值。
lb float | None 下界。
ub float | None 上界。
name str | None 变量名。

返回值Expr,连续决策变量。

# 1. 创建比例变量,限制在 0 到 1 之间。
ratio = builder.float_var(default=0.0, lb=0.0, ub=1.0, name="ratio")

# 2. 用比例变量表达连续成本。
builder.minimize(ratio * 100.0, name="scaled_cost")

set_var

标签HEURISTIC

签名set_var(size: int, *, default: list[int] | set[int] | None = None, name: str | None = None) -> Expr

精确解边界

当前 CP-SAT / MILP canonical model 都没有集合变量表示;集合模型通常需要走启发式,或手动改写为 0/1 变量和线性约束。

参数 类型 含义
size int 候选元素数量,元素索引通常为 0..size-1
default list[int] | set[int] | None 初始选中集合。
name str | None 变量名。

返回值Expr,集合变量。

# 1. 表示从 5 个任务中选择一个子集,默认选择 0 和 2。
selected = builder.set_var(size=5, default={0, 2}, name="selected_jobs")

# 2. 限制最多选择 3 个任务。
builder.constraint(builder.set_len(selected) <= 3, name="max_selected")

sequence_var

标签HEURISTIC CP-SAT

签名sequence_var(size: int, *, default: list[int] | None = None, name: str | None = None) -> Expr

CP-SAT 边界

CP-SAT 当前只支持绑定到 no_overlap(sequence, *intervals) 的序列变量,并要求序列大小与 interval 数量一致。路线黑盒或单独序列约束仍应视为启发式语义。

参数 类型 含义
size int 序列元素数量。
default list[int] | None 初始排列;不传时默认为 list(range(size))
name str | None 变量名。

返回值Expr,序列变量。

# 1. 用序列变量表示 4 个地点的访问顺序。
route = builder.sequence_var(size=4, name="route")

# 2. 要求地点 2 必须在路线中出现。
builder.constraint(builder.sequence_contains(route, 2) == 1, name="visit_2")

interval_var

标签HEURISTIC CP-SAT

签名interval_var(*, start: int = 0, length: int = 0, lb_start: int | None = None, ub_start: int | None = None, lb_length: int | None = 0, ub_length: int | None = None, name: str | None = None) -> Expr

参数 类型 含义
start int 默认开始时间。
length int 默认持续时间。
lb_start / ub_start int | None 开始时间上下界。
lb_length / ub_length int | None 持续时间上下界。
name str | None interval 名称。

返回值Expr,调度 interval 变量。

# 1. 建立一个长度为 3、开始时间范围为 [0, 10] 的任务。
job = builder.interval_var(start=0, length=3, lb_start=0, ub_start=10, name="job_a")

# 2. 限制任务必须在时间 12 之前结束。
builder.constraint(builder.interval_end(job) <= 12, name="job_a_deadline")

abs

标签HEURISTIC CP-SAT

签名abs(expr: Expr | Any) -> Expr

MILP 边界

MILP 当前未自动把绝对值改写为辅助变量和线性约束。需要 MILP 精确解时,应在模型中显式线性化。

参数 类型 含义
expr Expr | Any 要取绝对值的表达式或字面量。

返回值Expr,绝对值表达式。

# 1. 计算变量距离目标值 5 的偏差。
distance = builder.abs(x - 5)

# 2. 最小化该偏差。
builder.minimize(distance, name="distance_to_target")

sum

标签HEURISTIC CP-SAT MILP

签名sum(*exprs: Expr | Any) -> Expr

参数 类型 含义
*exprs Expr | Any 要求和的表达式或字面量。

返回值Expr,求和表达式。

# 1. 把多个装载量变量聚合为总装载量。
total_load = builder.sum(load_a, load_b, load_c)

# 2. 登记容量约束。
builder.constraint(total_load <= 100, name="capacity")

min

标签HEURISTIC CP-SAT

签名min(*exprs: Expr | Any) -> Expr

参数 类型 含义
*exprs Expr | Any 要取最小值的表达式或字面量。

返回值Expr,最小值表达式。

# 1. 表示三个资源池中的最小剩余容量。
least_slack = builder.min(slack_a, slack_b, slack_c)

# 2. 最大化最小剩余容量,表达均衡目标。
builder.maximize(least_slack, name="balance_slack")

max

标签HEURISTIC CP-SAT

签名max(*exprs: Expr | Any) -> Expr

MILP 边界

min / max 当前不会自动降为 MILP 的辅助变量约束。需要 MILP 时,应手动写成线性 epigraph / hypograph 形式。

参数 类型 含义
*exprs Expr | Any 要取最大值的表达式或字面量。

返回值Expr,最大值表达式。

# 1. 找到多台机器里的峰值负载。
peak_load = builder.max(load_a, load_b, load_c)

# 2. 最小化峰值负载。
builder.minimize(peak_load, name="minimize_peak_load")

and_

标签HEURISTIC CP-SAT

签名and_(lhs: Expr | Any, rhs: Expr | Any) -> Expr

参数 类型 含义
lhs Expr | Any 左侧逻辑表达式。
rhs Expr | Any 右侧逻辑表达式。

返回值Expr,逻辑与表达式。

# 1. 同时检查两个条件是否成立。
both_ready = builder.and_(machine_ready == 1, material_ready == 1)

# 2. 要求两个条件都成立后才能生产。
builder.constraint(both_ready == 1, name="ready_to_run")

or_

标签HEURISTIC CP-SAT

签名or_(lhs: Expr | Any, rhs: Expr | Any) -> Expr

参数 类型 含义
lhs Expr | Any 左侧逻辑表达式。
rhs Expr | Any 右侧逻辑表达式。

返回值Expr,逻辑或表达式。

# 1. 至少选择一种加急方式。
fast_mode = builder.or_(use_air == 1, use_express == 1)

# 2. 把可选规则登记为约束。
builder.constraint(fast_mode == 1, name="need_fast_mode")

not_

标签HEURISTIC CP-SAT

签名not_(expr: Expr | Any) -> Expr

参数 类型 含义
expr Expr | Any 要取反的逻辑表达式。

返回值Expr,逻辑非表达式。

# 1. 表示不能同时禁用某个安全开关。
disabled = builder.not_(safety_enabled == 1)

# 2. 禁止 disabled 为真。
builder.constraint(disabled == 0, name="safety_required")

iif

标签HEURISTIC

签名iif(cond: Expr | Any, when_true: Expr | Any, when_false: Expr | Any) -> Expr

精确解边界

iif 当前没有 CP-SAT 或 MILP lowering。需要精确解时,应把条件逻辑改写为后端可接收的布尔约束或线性化形式。

参数 类型 含义
cond Expr | Any 条件表达式。
when_true Expr | Any 条件为真时的值。
when_false Expr | Any 条件为假时的值。

返回值Expr,条件表达式。

# 1. 如果使用加急模式,成本为 100,否则成本为 30。
cost = builder.iif(use_fast == 1, 100, 30)

# 2. 把条件成本作为目标。
builder.minimize(cost, name="mode_cost")

set_len

标签HEURISTIC

签名set_len(set_expr: Expr | Any) -> Expr

参数 类型 含义
set_expr Expr | Any 集合变量或集合表达式。

返回值Expr,集合大小表达式。

# 1. 计算当前选择集合的元素数量。
selected_count = builder.set_len(selected)

# 2. 限制最多选择 2 个元素。
builder.constraint(selected_count <= 2, name="selection_limit")

set_contains

标签HEURISTIC

签名set_contains(set_expr: Expr | Any, value_expr: Expr | Any) -> Expr

参数 类型 含义
set_expr Expr | Any 集合变量或集合表达式。
value_expr Expr | Any 要检查的元素值。

返回值Expr,元素是否属于集合的 0/1 表达式。

# 1. 检查任务 3 是否被选中。
has_job_3 = builder.set_contains(selected, 3)

# 2. 要求任务 3 必须被选中。
builder.constraint(has_job_3 == 1, name="need_job_3")

sequence_contains

标签HEURISTIC

签名sequence_contains(sequence_expr: Expr | Any, value_expr: Expr | Any) -> Expr

CP-SAT 边界

sequence_contains 当前不属于 CP-SAT sequence lowering 支持面。CP-SAT 只支持 sequence_varno_overlap 组合出的排序约束。

参数 类型 含义
sequence_expr Expr | Any 序列变量或序列表达式。
value_expr Expr | Any 要检查的元素值。

返回值Expr,元素是否出现在序列中的 0/1 表达式。

# 1. 检查地点 2 是否在路线中。
visits_2 = builder.sequence_contains(route, 2)

# 2. 要求路线必须访问地点 2。
builder.constraint(visits_2 == 1, name="visit_2")

all_different

标签HEURISTIC CP-SAT

签名all_different(*exprs: Expr | Any) -> Expr

参数 类型 含义
*exprs Expr | Any 要求互不相同的一组表达式。

返回值Expr,互异约束表达式。

# 1. 三个任务必须分配到不同工位。
different_stations = builder.all_different(station_a, station_b, station_c)

# 2. 将互异关系登记为正式约束。
builder.constraint(different_stations, name="all_different_stations")

element

标签HEURISTIC

签名element(array_values: list[int | float], index_expr: Expr | Any) -> Expr

参数 类型 含义
array_values list[int | float] 常量数组。
index_expr Expr | Any 取值索引表达式。

返回值Exprarray_values[index_expr] 对应的表达式。

# 1. choice 决定选择哪个成本项。
choice = builder.int_var(default=0, lb=0, ub=2, name="choice")

# 2. 根据 choice 从常量数组中取成本。
picked_cost = builder.element([5, 8, 13], choice)

# 3. 最小化被选中的成本。
builder.minimize(picked_cost, name="picked_cost")

table

标签HEURISTIC

签名table(exprs: list[Expr | Any], allowed_tuples: list[list[int]]) -> Expr

精确解边界

element / table 当前未接入 CP-SAT 原生约束,也未线性化到 MILP。

参数 类型 含义
exprs list[Expr | Any] 需要联合限制的一组表达式。
allowed_tuples list[list[int]] 允许出现的元组列表。

返回值Expr,表约束表达式。

# 1. x 和 y 只能取 (0, 1) 或 (1, 0),等价于二选一。
allowed_pair = builder.table([x, y], [[0, 1], [1, 0]])

# 2. 登记允许元组表约束。
builder.constraint(allowed_pair, name="xor_pairs")

interval_start

标签HEURISTIC CP-SAT

签名interval_start(interval_expr: Expr | Any) -> Expr

参数 类型 含义
interval_expr Expr | Any interval 变量或表达式。

返回值Expr,interval 的开始时间表达式。

# 1. 读取任务开始时间。
start = builder.interval_start(job)

# 2. 要求任务不能早于时间 2 开始。
builder.constraint(start >= 2, name="release_time")

interval_end

标签HEURISTIC CP-SAT

签名interval_end(interval_expr: Expr | Any) -> Expr

参数 类型 含义
interval_expr Expr | Any interval 变量或表达式。

返回值Expr,interval 的结束时间表达式。

# 1. 读取任务结束时间。
end = builder.interval_end(job)

# 2. 要求任务在工期窗口内完成。
builder.constraint(end <= 10, name="deadline")

interval_length

标签HEURISTIC CP-SAT

签名interval_length(interval_expr: Expr | Any) -> Expr

参数 类型 含义
interval_expr Expr | Any interval 变量或表达式。

返回值Expr,interval 的持续时间表达式。

# 1. 读取任务持续时间。
duration = builder.interval_length(job)

# 2. 限制持续时间不能超过 4。
builder.constraint(duration <= 4, name="duration_limit")

cumulative

标签HEURISTIC CP-SAT

签名cumulative(intervals: list[Expr | Any], demands: list[Expr | Any], capacity: Expr | Any) -> Expr

参数 类型 含义
intervals list[Expr | Any] 占用资源的 interval 列表。
demands list[Expr | Any] 每个 interval 的资源需求。
capacity Expr | Any 资源容量。

返回值Expr,累积资源约束表达式。

# 1. 两个任务都占用同一台容量为 1 的机器。
machine_capacity = builder.cumulative([job_a, job_b], [1, 1], 1)

# 2. 登记容量约束,避免同时超载。
builder.constraint(machine_capacity, name="machine_capacity")

no_overlap

标签HEURISTIC CP-SAT

签名no_overlap(sequence_expr: Expr | Any, *interval_exprs: Expr | Any) -> Expr

参数 类型 含义
sequence_expr Expr | Any 表示任务顺序的序列变量。
*interval_exprs Expr | Any 需要互不重叠的 interval。

返回值Expr,不重叠约束表达式。

# 1. sequence_var 表示同一机器上的任务顺序。
order = builder.sequence_var(2, name="machine_order")

# 2. no_overlap 约束 job_a 和 job_b 不能同时占用机器。
builder.constraint(builder.no_overlap(order, job_a, job_b), name="no_overlap")

precedence

标签HEURISTIC CP-SAT

签名precedence(before_interval: Expr | Any, after_interval: Expr | Any, *, lag: Expr | int = 0) -> Expr

MILP 边界

cumulativeno_overlapprecedence 属于调度结构约束。当前 MILP 路径不自动生成对应线性 formulation。

参数 类型 含义
before_interval Expr | Any 必须先完成的 interval。
after_interval Expr | Any 后续 interval。
lag Expr | int 两个 interval 之间的最小间隔。

返回值Expr,前后工序约束表达式。

# 1. job_a 完成后至少间隔 1 个时间单位才能开始 job_b。
a_before_b = builder.precedence(job_a, job_b, lag=1)

# 2. 登记工序先后关系。
builder.constraint(a_before_b, name="a_before_b")

external_call

标签HEURISTIC

签名external_call(fn: Callable[..., Any], *inputs: Expr | Any, name: str | None = None, value_kind: ValueKind = ValueKind.SCALAR, timeout_ms: int | None = None, cache: bool = True) -> Expr

精确解边界

CP-SAT / MILP 不能调用任意 Python 函数并证明全局最优。包含 external_call 的目标或约束会使 exact lowering 拒绝该路径。

参数 类型 含义
fn Callable[..., Any] Python 外部评估函数。
*inputs Expr | Any 传给外部函数的输入表达式。
name str | None 外部调用名;不传时使用函数名。
value_kind ValueKind 外部调用返回值类型,默认标量。
timeout_ms int | None 单次调用超时毫秒数。
cache bool 是否缓存相同输入的评估结果。

返回值Expr,外部调用结果表达式。

def route_score(route: list[int]) -> int:
    # 1. 在外部函数中实现暂时无法线性化的业务评分。
    return len(route)


# 2. 用序列变量表达待优化的路线。
route = builder.sequence_var(5, name="route")

# 3. 将 Python 函数接入模型图,作为可被求解器调用的黑盒节点。
score = builder.external_call(route_score, route, name="route_score", timeout_ms=100)

# 4. 把黑盒评分登记为目标。
builder.minimize(score, name="score")

constraint

标签MODEL

签名constraint(expr: Expr | Any, *, name: str | None = None) -> Expr

参数 类型 含义
expr Expr | Any 布尔表达式或关系表达式。
name str | None 约束名称。

返回值Expr,已登记的约束节点。

# 1. 先构造容量关系表达式。
capacity_ok = x + y <= 10

# 2. 再调用 constraint,把关系加入模型约束列表。
builder.constraint(capacity_ok, name="capacity")

约束必须登记

单独写 x + y <= 10 只会创建表达式,不会进入模型约束列表。需要显式调用 constraint(...)

minimize

标签MODEL

签名minimize(expr: Expr | Any, *, name: str | None = None) -> Expr

参数 类型 含义
expr Expr | Any 要最小化的目标表达式。
name str | None 目标名称。

返回值Expr,已登记的目标节点。

# 1. 构造总成本表达式。
total_cost = fixed_cost + variable_cost

# 2. 登记最小化目标。
builder.minimize(total_cost, name="total_cost")

maximize

标签MODEL

签名maximize(expr: Expr | Any, *, name: str | None = None) -> Expr

精确解边界

constraintminimizemaximize 本身只是登记接口。能否走 CP-SAT 或 MILP,取决于被登记表达式里的变量、算子和约束类型。

参数 类型 含义
expr Expr | Any 要最大化的目标表达式。
name str | None 目标名称。

返回值Expr,已登记的目标节点。

# 1. 构造收益表达式。
profit = (x * 3) + (y * 2)

# 2. 登记最大化目标。
builder.maximize(profit, name="profit")

to_program_spec

标签MODEL

签名to_program_spec() -> ProgramSpec

参数:无。

返回值ProgramSpec,可序列化的模型结构描述。

# 1. 导出中间结构,适合调试或持久化检查。
spec = builder.to_program_spec()

# 2. 查看变量、约束、目标节点数量。
print(len(spec.variable_ids), len(spec.constraint_ids), len(spec.objective_ids))

freeze

标签MODEL

签名freeze() -> ExecutableProgram

参数:无。

返回值ExecutableProgram,可交给 Orchestrator().run(...) 的可执行模型。

# 1. 在变量、约束、目标都登记完成后冻结模型。
program = builder.freeze()

# 2. 冻结后的 program 是公开求解入口的输入。
result = Orchestrator().run(program)