建模接口¶
各接口的 CP-SAT、HiGHS 限制见求解器支持矩阵;方法详情中的标签区分支持、条件支持和不支持。
OptModel() 拥有全部变量、表达式、约束与目标;不能跨模型组合表达式。
保存与读取模型文件¶
model.save(path) 将模型保存为 .pb,或按 .pb.gz 后缀进行 gzip 压缩。
read_model(path) 识别这两种格式,返回可继续编辑和求解的 OptModel。
PB 模型持有不可变内存快照,查询、直接求解和结果读取无需完整恢复 Python 建模图,首次修改才恢复。
加载完成后覆盖或删除原文件不影响模型;原生解析和编译仍会执行。
声明集合及嵌套值支持序列、映射和集合操作;修改应通过模型取得的对象进行。
插入的外部可变容器由模型复制持有,后续修改原容器不会改变模型。
这些集合不保证内置 list、dict、set 的具体类型;浅拷贝保留嵌套共享,
深拷贝产生独立普通容器并保留原模型表达式句柄。求解及交互会话期间,包含旧引用在内的模型写入会被拒绝。
from optagent import OptModel, read_model, solve
model = OptModel()
x = model.int(0, 10, name="x")
model.minimize(x)
model.save("model.pb.gz") # 也可用 model.pb 保存未压缩文件
loaded = read_model("model.pb.gz")
loaded_x = loaded.decisions[0]["expression"]
loaded.add_constraint(loaded_x >= 4)
solution = solve(loaded)
这两种格式保留模型标识、表达式图、变量域、声明初值、名称、约束和目标顺序,
包括非线性表达式、集合、序列、区间及已经确定类型的模型 Lambda。
文件不保存求解结果或 Python 代码;保存不会使当前解值失效,加载后的模型需重新求解才能读取 .value。
含外部 Python 回调的模型无法独立恢复,保存和加载均抛出 ValueError。
保存路径接受字符串或 pathlib.Path,后缀不区分大小写,父目录必须已存在。
已有文件只在写入成功后被替换。压缩使用 gzip 级别 6,无需额外安装压缩依赖,实际压缩比例取决于模型内容。
文件读取也兼容现有编码器生成的版本 1 模型字节及其 gzip 压缩形式。
损坏的压缩数据、无效引用和无法完整恢复的协议字段会被拒绝;具体算子的语义及后端兼容性仍由求解编译阶段检查。
从 MPS / LP 文件导入¶
read_model(path) 返回普通的 OptModel,可继续添加约束或目标,然后调用现有的 solve(model)。
from optagent import read_model, solve
model = read_model("problem.mps") # 也支持 problem.lp
solution = solve(model, time_limit_s=10)
if solution.feasible:
for decision in model.decisions:
print(decision["name"], decision["expression"].value)
path 接受字符串或 pathlib.Path;相对路径以当前工作目录为基准,扩展名不区分大小写。
读取使用随包提供的原生读取器,无需另外安装 highspy。读取阶段不运行求解,也不设置用户初值。
支持未压缩的 .mps 和 CPLEX .lp 中的单目标线性规划、混合整数线性规划。
变量名、约束名、目标方向和目标常数项会保留;未命名声明可保留空名称,模型标识取文件名去掉扩展名。
通过 model.decisions 按导入顺序访问变量声明及表达式。名称不要求唯一,不应在名称重复时直接转成字典。
整数域 [0, 1] 转成布尔变量;固定为 0 或 1 的整数仍保留固定域。
整数上下界向内取整,有限整数边界的绝对值不得超过 2^53;无穷边界表示为无显式界。
双边约束拆成两条约束,两条沿用原约束名称。系数采用读取器的双精度表示。
MPS / LP 导入暂不支持压缩文件、二次项、SOS、指示约束、半连续/半整数变量和多目标扩展。
受当前读取器限制,LP 中的 /* ... */ 块注释会被拒绝,请改用反斜杠开头的行注释。
MPS 读取器产生警告时拒绝导入,包括忽略输入数据或回退到另一种解析方式的警告。
应修正文件或重新导出为读取器接受的格式,再重试。
路径类型错误抛出 TypeError,文件访问错误抛出 OSError 的相应子类;
无效或不支持的模型抛出 ValueError,原生读取器不可用时抛出 RuntimeError。
导入成功只表示模型可以构造;各求解入口仍遵循求解器支持矩阵中的限制。
变量工厂¶
| 方法 | 参数 | 语义 |
|---|---|---|
bool |
default |
布尔决策 |
int |
lb=None、ub=None、default |
整数决策,边界包含端点 |
float |
lb=None、ub=None、default |
浮点决策,边界包含端点 |
set |
universe_size、default |
range(universe_size) 中的不重复成员,无序 |
list |
universe_size、default |
同一整数宇宙中的不重复成员,有序 |
interval |
min_start=0、max_end=0、default |
必选区间,允许零长度 |
optional_interval |
min_start=0、max_end=0、default |
可缺席区间 |
布尔变量参与 <、<=、>、>= 时按 0/1 比较,支持两个布尔变量直接比较。
例如 h >= y 表示 y 为真时 h 必须为真;== 和 != 仍保持布尔相等与不等语义。
default 省略时没有用户指定初值,内核负责初始构造。集合 / 序列初值为整数成员迭代器;区间初值使用含 start、end、present 的映射。初值必须符合变量域,不会自动成为约束。
约束与目标¶
| 方法 | 用法 |
|---|---|
constraint(expression) |
add_constraint 的别名,添加约束 |
minimize(expression) |
追加最小化目标 |
maximize(expression) |
追加最大化目标 |
多个目标按声明顺序进行字典序比较。模型变更使旧值失效。
表达式与算子¶
| 类别 | 主要接口 |
|---|---|
| 算术与聚合 | sum、prod、min、max、sub、div、mod、abs、dist、pow |
| 比较与逻辑 | eq、neq、geq、leq、gt、lt、and_、or_、not_、xor、iif |
| 数学函数 | sqrt、sin、cos、round、ceil、floor、log、exp |
| 集合关系 | partition、disjoint、cover、union、intersection |
| 容器与索引 | array、range、at、count、contains、index、find、distinct、sort |
| 区间 | start、end、length、presence、hull |
| 高阶表达式 | lambda_function、call、piecewise、step_array |
常用算术与比较也可直接使用 Python 运算符。聚合方法支持的方法重载与容器类型并非完全相同,详见下方方法说明。
Expression 与 IntervalExpression¶
表达式提供 model、type、operator、operands 和 value。.value 读取最新求解结果;没有值或模型变更后读取会抛出 RuntimeError。
expression[index] 创建索引表达式。expression.at(*indices, default=...) 可声明越界时的默认值。区间表达式还提供 .start、.end、.length 属性与 .presence() 方法。
外部函数¶
通过 create_int_external_function、create_double_external_function、create_int_array_external_function、create_double_array_external_function 注册 Python 回调,得到 ExternalFunction。调用该对象构造表达式,回调在求解评价时接收一个参数视图。
from optagent import OptModel
model = OptModel()
x = model.int(0, 10)
def evaluate_cost(args):
return (args[0] - 3) ** 2
cost = model.create_int_external_function(evaluate_cost)
model.minimize(cost(x))
solution = model.solve(time_limit_s=1.0, deterministic=False, external_evaluation_limit=100)
回调可以包含普通 Python 分支、循环或外部请求。在一次求解中,相同带类型输入的结果必须稳定;求解器可能复用结果,也可能重复调用。不能依赖每次评价都执行回调。回调返回值须符合注册的标量 / 数组类型,默认串行执行。
包含外部回调的模型可使用 solve() 或 solve_heuristic(),需设置 deterministic=False。精确求解的 HiGHS 和 CP-SAT 后端均不支持外部回调。
add_evaluation_point(arguments, value) 注册已知评价点,命中时直接复用,不执行回调、不消耗调用额度。整数与浮点输入分别匹配,例如 [3] 与 [3.0] 不相同。相同带类型输入登记不同结果,会在求解启动时报错。已知点在当前求解中固定,求解期间修改登记列表不会改变当前结果。
已知点不再自动覆盖初始解。需要从已知方案开始时,显式设置决策变量的 default,例如 model.int(0, 10, default=3)。旧代码若依赖自动热启动,需要补上显式初值。
浮点函数的 grad 参数保留兼容,当前搜索算法不使用登记的梯度。
求解结果¶
Solution 包含 feasible、objectives、status、solver_name、diagnostics;见结果字段说明。
可选名称与结果读取¶
通常直接使用 OptModel(),变量、约束和目标也无需声明 name。保留 Python 变量引用,在求解成功后通过表达式的 .value 读值;solution.objectives 按目标声明顺序排列。
model_id 与 name 均为可选标识,默认空字符串,不是结果查询键。只有实际需要标识时才显式设置。完整参数仍列在方法详情中。