跳转至
1.2.2

建模接口

各接口的 CPSAT、MATHOPT、OPTX 限制见求解器支持矩阵;方法详情中的标签区分支持、条件支持和不支持。

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 分支、循环或外部请求。在一次求解中,相同带类型输入的结果必须稳定;求解器可能复用结果,也可能重复调用。不能依赖每次评价都执行回调。回调返回值须符合注册的标量 / 数组类型,外部函数使用本地搜索路径,默认串行执行。

add_evaluation_point(arguments, value) 注册已知评价点,命中时直接复用,不执行回调、不消耗调用额度。整数与浮点输入分别匹配,例如 [3] 与 [3.0] 不相同。相同带类型输入登记不同结果,会在求解启动时报错。已知点在当前求解中固定,求解期间修改登记列表不会改变当前结果。

已知点不再自动覆盖初始解。需要从已知方案开始时,显式设置决策变量的 default,例如 model.int(0, 10, default=3)。旧代码若依赖自动热启动,需要补上显式初值。

浮点函数的 grad 参数保留兼容,当前搜索算法不使用登记的梯度。

求解结果

Solution 包含 feasible、objectives、status、solver_name、diagnostics;见结果字段说明。

查看全部 OptModel 方法详情 →

可选名称与结果读取

通常直接使用 OptModel(),变量、约束和目标也无需声明 name。保留 Python 变量引用,在求解成功后通过表达式的 .value 读值;solution.objectives 按目标声明顺序排列。

model_id 与 name 均为可选标识,默认空字符串,不是结果查询键。只有实际需要标识时才显式设置。完整参数仍列在方法详情中。