跳转至
OptAgent 1.2.0

ModelBuilder

ModelBuilder 是公开建模入口。按问题需求选择建模方式见 指南

本页按接口逐项给出用途、调用形式、参数、返回值和带注释示例。调用形式省略 Python 的关键字参数分隔符;除第一个业务输入外,可选参数建议按名称传入。

精确解支持矩阵

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

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

标签含义:

标签 含义
HEURISTIC 启发式路径可评估或搜索该接口表达的模型语义。
CP-SAT 当前 CP-SAT 精确路径可 lowering 到 cp_sat
MILP 当前 MILP 精确路径可 lowering 到 mathopt_mp / highs_cpp
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,或作为直接 sequence_transition_sum objective 输入 不支持 CP-SAT 对调度序列用 rank 变量,对 sequence graph objective 用显式 position/item assignment。
interval_var / optional_interval_var HEURISTIC CP-SAT 支持 mandatory / optional interval 不支持 Optional interval 需要 bool_var 或布尔常量作为 presence。MILP 当前只做线性 MP lowering,不接收 interval 结构。
abs HEURISTIC CP-SAT 支持 不支持 MILP 当前未线性化绝对值,需要用户手动改写为线性约束。
sum HEURISTIC CP-SAT MILP 支持 支持线性求和 MILP 要求所有输入保持线性。
at_most_one / at_least_one / exactly_one HEURISTIC CP-SAT MILP 支持布尔/整数输入 支持线性布尔计数 这些方法返回 sum(...) 比较表达式,兼容性取决于输入表达式。
min / max HEURISTIC CP-SAT 支持 不支持 MILP 当前未自动引入辅助变量和 epigraph 约束。
and_ / or_ / not_ HEURISTIC CP-SAT 支持布尔表达式 不支持 MILP 当前不做逻辑重写或 big-M 线性化。
iif HEURISTIC CP-SAT 支持整数条件选择 不支持 CP-SAT 会用 enforcement literal 降为辅助整数变量;MILP 当前不做 big-M 线性化。
set_len / set_contains HEURISTIC 不支持 不支持 依赖集合变量,当前 exact canonical model 不包含集合语义。
sequence_contains HEURISTIC CP-SAT 仅支持常量 membership check 不支持 对排列型 sequence_var,常量在 [0, size) 内为恒真,否则恒假。
sequence_transition_sum HEURISTIC CP-SAT 支持 IR-owned dense integer path/cycle objective 不支持 CP-SAT 只支持直接 objective root、min sense、非负整数成本;sparse/forbidden/default-cost 和 score 语义会显式拒绝。
sequence_view / sequence_successor HEURISTIC 不支持 不支持 optional-aware active view 与直接后继表达式;exact route 明确拒绝。
sequence_transition HEURISTIC 不支持 不支持 active view 上的 typed cost/validity;支持稀疏禁止边。
sequence_dimension / sequence_setup HEURISTIC 不支持 不支持 标量前缀状态、reset 和资源 setup gap;exact route 明确拒绝。
all_different HEURISTIC CP-SAT 支持 不支持 MILP 当前不自动构造 pairwise 或 assignment 线性化。
element / table HEURISTIC 不支持 不支持 当前 exact backend 没有 element/table 原生或线性化实现。
interval_start / interval_end / interval_length / interval_presence HEURISTIC CP-SAT 支持 不支持 只在 CP-SAT interval 模型中可用。interval_presence 对 mandatory interval 返回恒真表达式。
selected_start / selected_end / selected_duration HEURISTIC CP-SAT 支持 不支持 通过 presence-controlled iif 投影被选中的 optional interval;调用方仍需约束 exactly-one。
alternative / add_alternative HEURISTIC CP-SAT MILP 支持 支持线性布尔计数 alternative 返回 exactly-one 表达式;add_alternative 同时登记约束。
cumulative / no_overlap / precedence HEURISTIC CP-SAT 支持 不支持 调度约束当前走 CP-SAT;MILP 不做调度结构线性化。
external_call HEURISTIC 不支持 不支持 精确解后端不能调用任意 Python 黑盒函数并证明全局最优。
constraint / minimize / maximize MODEL 取决于内部表达式 取决于内部表达式 登记接口本身可用,精确解兼容性由包裹的表达式决定。
to_program_spec / freeze MODEL 高级 高级 导出或编译模型结构;普通求解请直接 solve(builder)

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

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

接口分组

分组 方法
常量与变量 constbool_varint_varfloat_varset_varsequence_varinterval_varoptional_interval_var
数值与逻辑表达式 abssumat_most_oneat_least_oneexactly_oneminmaxand_or_not_iif
集合与序列 set_lenset_containssequence_containssequence_transition_sumsequence_viewsequence_successorsequence_transitionsequence_dimensionsequence_setupall_differentelementtable
调度 interval_startinterval_endinterval_lengthinterval_presenceselected_startselected_endselected_durationalternativeadd_alternativecumulativeno_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[bool]

参数 类型 含义
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[int]

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[float]

参数 类型 含义
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[list[int]]

精确解边界

当前 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[list[int]]

CP-SAT 边界

CP-SAT 当前支持两类序列:绑定到 no_overlap(sequence, *intervals) 的调度序列,以及作为直接 sequence_transition_sum(...) objective 输入的 dense integer sequence graph。路线黑盒或其它单独序列约束仍应视为启发式语义。

参数 类型 含义
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[dict[str, int]]

参数 类型 含义
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")

optional_interval_var

标签HEURISTIC CP-SAT

签名optional_interval_var(presence: Expr | bool, 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[dict[str, int]]

创建由 presence 控制的 optional interval。interval 的结构始终存在;no_overlap(...)precedence(...) 等 optional-aware 调度约束会根据 presence 判断它是否参与。

presence 限制

presence 必须是 bool_var(...) 或布尔常量,不能是任意比较表达式。需要复杂 presence 逻辑时,先建布尔变量,再用额外约束绑定它。

参数 类型 含义
presence Expr | bool 控制 interval 是否启用的布尔变量或布尔常量。
start / length int 默认开始时间和持续时间。
lb_start / ub_start int | None 开始时间上下界。
lb_length / ub_length int | None 持续时间上下界。
name str | None interval 名称。

返回值Expr,optional interval 变量。

# 1. presence 决定该加工方式是否被选择。
use_machine_a = builder.bool_var(name="op10_on_machine_a")

# 2. 创建可选 interval。
op10_a = builder.optional_interval_var(
    presence=use_machine_a,
    start=0,
    length=3,
    lb_start=0,
    ub_start=20,
    lb_length=3,
    ub_length=3,
    name="op10_machine_a",
)

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")

at_most_one

标签HEURISTIC CP-SAT MILP

签名at_most_one(*bool_exprs: Expr | Any) -> Expr[bool]

返回“最多一个表达式为真”的关系表达式,等价于 sum(...) <= 1

choice_ok = builder.at_most_one(use_a, use_b, use_c)
builder.constraint(choice_ok, name="choose_at_most_one")

at_least_one

标签HEURISTIC CP-SAT MILP

签名at_least_one(*bool_exprs: Expr | Any) -> Expr[bool]

返回“至少一个表达式为真”的关系表达式,等价于 sum(...) >= 1

has_mode = builder.at_least_one(use_a, use_b, use_c)
builder.constraint(has_mode, name="choose_at_least_one")

exactly_one

标签HEURISTIC CP-SAT MILP

签名exactly_one(*bool_exprs: Expr | Any) -> Expr[bool]

返回“恰好一个表达式为真”的关系表达式,等价于 sum(...) == 1

one_machine = builder.exactly_one(use_machine_a, use_machine_b)
builder.constraint(one_machine, name="select_one_machine")

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 CP-SAT

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

精确解边界

CP-SAT 支持整数条件选择。MILP 当前不自动把 iif 改写为 big-M 线性化。

参数 类型 含义
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_transition_sum

标签HEURISTIC CP-SAT

签名sequence_transition_sum(sequence: Expr, graph: TransitionGraph | list[list[int | float]] | dict, include_return_edge: bool = False, cost_semantics: str = "penalty", sparse_edge_semantics: str = "default_cost", default_edge_cost: int | float | None = None) -> Expr

计算序列变量按给定转换图的总转换成本。通常作为 minimize(...) 的目标。

CP-SAT 边界

CP-SAT 当前只支持 dense non-negative integer cost matrix、min sense、作为 objective root 的使用方式。sparse / forbidden / default-cost / score / non-min / negative 或非整数成本模式不做 exact lowering。

参数 类型 含义
sequence Expr 序列变量(来自 sequence_var())。
graph TransitionGraph \| list[list] \| dict 转换成本图。推荐使用 TransitionGraph builder 对象,也接受 dense matrix 或 raw dict。
include_return_edge bool 是否包含回路边(最后元素到第一个元素的成本)。False 为 path,True 为 cycle。
cost_semantics str "penalty""distance""score";CP-SAT exact 当前只接受前两种成本语义。
sparse_edge_semantics str "default_cost" 使用默认成本,"forbidden" 禁止缺失边,"implicit" 将缺失边视为隐式零成本。
default_edge_cost int \| float \| None 稀疏图中缺失边的默认成本值。仅在 sparse_edge_semantics="default_cost" 时生效。

返回值Expr,标量成本表达式。

使用 TransitionGraph builder(推荐)

from optagent import ModelBuilder, TransitionGraph

builder = ModelBuilder()
route = builder.sequence_var(size=4, name="route")

# Dense matrix
g = TransitionGraph.from_matrix([
    [0, 4, 7, 3],
    [2, 0, 5, 8],
    [3, 11, 0, 6],
    [9, 1, 4, 0],
])
cost = builder.sequence_transition_sum(route, g)
builder.minimize(cost, name="travel_cost")

稀疏图 + fluent edge builder

g = (TransitionGraph(size=4)
     .edge(0, 1, cost=4)
     .edge(1, 2, cost=5)
     .edge(2, 3, cost=6)
     .default_cost(10))
cost = builder.sequence_transition_sum(route, g)

带回路边(cycle)

# include_return_edge=True 时计算完整回路成本(TSP)
cost = builder.sequence_transition_sum(route, g, include_return_edge=True)
builder.minimize(cost, name="tsp_cost")

直接传入 dense matrix

# 也可以直接传 list[list[int]] 作为 graph 参数
matrix = [[0, 4, 7], [2, 0, 5], [3, 11, 0]]
cost = builder.sequence_transition_sum(route, matrix)

Active scheduling sequence nodes

这些 low-level 方法承载 SchedulingModel 高级 sequence 语义:

方法 返回语义
sequence_view(sequence, presences, item_ids, name=None) 按静态 item ID 和 presence 投影 active sequence。
sequence_successor(sequence, before_item_id, after_item_id) 两个 item 是否直接相邻。
sequence_transition(sequence, graph, item_types, ...) typed path 的转换成本或允许边有效性。
sequence_dimension(sequence, initial_value, contributions, item_types, reset_item_ids, reset_type_edges, query_item_id, query, ...) 指定 item 的累计前后值、段号、段总量或段边界。
sequence_setup(sequence, intervals, graph, item_types, ...) 相邻类型所需 setup 是否可被任务间隙和资源 calendar 容纳。

通常应通过 Resource.sequence().view() 上的 transition()setup_time()dimension() 使用这些节点。它们当前只支持 heuristic runtime;direct exact lowering 会 fail fast。

sequence_contains

标签HEURISTIC CP-SAT

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

CP-SAT 边界

CP-SAT 当前只支持常量 membership check。对排列型 sequence_var,常量在 [0, size) 内为恒真,否则恒假;动态 membership 表达式不做 exact lowering。

参数 类型 含义
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")

interval_presence

标签HEURISTIC CP-SAT

签名interval_presence(interval_expr: Expr | Any) -> Expr[bool]

返回 interval 的 presence 表达式。mandatory interval 返回复用的恒真常量;optional interval 返回创建时传入的 presence。

present = builder.interval_presence(op10_a)
builder.constraint(present == 1, name="force_op10_a")

selected_start

标签HEURISTIC CP-SAT

签名selected_start(intervals: list[Expr | Any] | tuple[Expr | Any, ...], presences: list[Expr | Any] | tuple[Expr | Any, ...]) -> Expr

返回 presence 为真的 interval 的开始时间。调用方需要另行保证 exactly-one presence。

start = builder.selected_start([op10_a, op10_b], [use_machine_a, use_machine_b])
builder.constraint(start >= 2, name="release_time")

selected_end

标签HEURISTIC CP-SAT

签名selected_end(intervals: list[Expr | Any] | tuple[Expr | Any, ...], presences: list[Expr | Any] | tuple[Expr | Any, ...]) -> Expr

返回 presence 为真的 interval 的结束时间。常用于 flexible scheduling 中计算 task 完工时间。

end = builder.selected_end([op10_a, op10_b], [use_machine_a, use_machine_b])
builder.constraint(end <= 20, name="deadline")

selected_duration

标签HEURISTIC CP-SAT

签名selected_duration(intervals: list[Expr | Any] | tuple[Expr | Any, ...], presences: list[Expr | Any] | tuple[Expr | Any, ...]) -> Expr

返回 presence 为真的 interval 的持续时间。

duration = builder.selected_duration([op10_a, op10_b], [use_machine_a, use_machine_b])
builder.minimize(duration, name="selected_duration")

alternative

标签HEURISTIC CP-SAT MILP

签名alternative(*presence_exprs: Expr | Any) -> Expr[bool]

返回 exactly-one alternative 表达式。它不会自动登记约束,需要传给 constraint(...),或直接使用 add_alternative(...)

choice = builder.alternative(use_machine_a, use_machine_b)
builder.constraint(choice, name="op10_select_one_machine")

add_alternative

标签HEURISTIC CP-SAT MILP

签名add_alternative(*presence_exprs: Expr | Any, name: str | None = None) -> Expr[bool]

创建并登记 exactly-one alternative 约束。

builder.add_alternative(use_machine_a, use_machine_b, name="op10_select_one_machine")

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, name=None, value_kind="scalar", timeout_ms=None, pure=True, deterministic=True, cacheable=None, batch_fn=None, batch_safe=None, concurrency_mode="shared_serial", worker_factory=None, error_policy="fail", depends_on=()) -> Expr

精确解边界

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

参数 类型 含义
fn Callable[[ExternalCallbackContext], Any] Python 外部评估函数,必须是 fn(ctx) 形式。
name str | None 外部调用名;不传时使用函数名。
value_kind str 外部调用返回值类型,默认 "scalar"
timeout_ms int | None 单次调用超时毫秒数。
pure bool 回调是否无副作用。
deterministic bool 相同依赖值是否总是返回相同结果。
cacheable bool | None 是否缓存相同输入的评估结果;不传时由 puredeterministic 推导。
batch_fn Callable | None 可选批量评价函数,输入多行依赖值并返回等长结果。
batch_safe bool | None 是否允许批量调用;None 根据 batch_fn 推导。
concurrency_mode str "shared_serial""shared_parallel""worker_isolated"
worker_factory Callable | None worker-isolated 模式下为每个 worker 创建独立回调。
error_policy str "fail""skip_candidate"
depends_on tuple[Any, ...] | list[Any] 条件分支中 discovery 可能读不到的显式依赖。

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

from optagent import ExternalCallbackContext

route = builder.sequence_var(5, name="route")

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


# 2. 将 Python 函数接入模型图,依赖通过 ctx.value(...) 自动发现。
score = builder.external_call(route_score, name="route_score", timeout_ms=100)

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

ctx.value(route) 是推荐写法:route 的类型是 Expr[list[int]],因此静态类型检查器和 IDE 可以把返回值识别为 list[int]ctx.value("route") 仍然支持,用于动态按名称访问变量;这种写法的静态返回类型是 Any

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();直接传 buildersolve(...)to_program_spec() 生成的是可序列化 IR,会移除 Python callable。包含 external_call 的模型需要通过 solve(builder)builder.freeze() 保留 external provider。

签名to_program_spec() -> ProgramSpec

参数:无。

返回值ProgramSpec,可序列化的模型结构描述;它不是带 Python callback registry 的运行时对象。

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

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

freeze

标签MODEL

高级编译接口

solve(builder) 会自动完成这一步。只有在需要复用已编译运行对象、编写测试、或接入底层后端时,才需要显式调用 freeze()

签名freeze() -> ExecutableProgram

参数:无。

返回值ExecutableProgram,保留 external provider registry 的可执行模型。

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

# 2. 普通求解通常直接 solve(builder),这里用于复用编译结果。
solution = solve(program)