跳转至
1.2.2

结果与诊断

四个求解入口都返回 Solution。先检查是否有可行解,再读取变量和派生表达式的值。

安全读取结果

from optagent import OptModel

model = OptModel()
x = model.int(0, 10)
cost = 2 * x
model.constraint(x >= 3)
model.minimize(cost)
solution = model.solve(time_limit_s=1.0, log_level="off")

print(solution.status, solution.solver_name)
if solution.feasible:
    print(solution.objectives)
    print(x.value, cost.value)
else:
    print(solution.diagnostics)
字段 如何使用
feasible 是否取得可行赋值;不能用 False 单独判断无解
objectives 按模型声明顺序排列的目标值元组
status 终止状态;不同路径的字符串与大小写可能不同
solver_name 当前包装层标识:search、highs、cpsat、mathopt
diagnostics 路径相关的诊断字典;用 .get() 读取可选字段
best_bound OptX 后端报告的单目标界限;未独立认证,不可用时为 None
gap OptX 后端报告的相对间隙比值,0.001 表示 0.1%;不可用时为 None
solve_time OptX 后端搜索运行秒数,包含后端重试;不可用时为 None

best_bound 对最小化目标是下界,对最大化目标是上界。它与 gap 描述后端编译问题及其候选, 并不表示通过原模型最优性认证;数值修正后的 objectives 可能与后端候选目标有差异。 多目标模型只在 diagnostics["backend_attempts"] 中按 objective_index 提供各阶段指标, 不会将某一阶段的界限当成整个问题的 best_bound。其他求解路径当前不填充这三个便捷属性。 solve_time 不含模型转换、原模型验解、连续变量修正或独立认证;完整调用耗时可由业务端计时。

OptX 的结论与后端信息

status、feasible 和 objectives 给出 OptAgent 本次求解的最终结论。 后端信息保留在 diagnostics 中,可按需查询,无需调用者另行选择验证层级:

print(solution.status, solution.feasible, solution.objectives)
print(solution.diagnostics.get("backend_status"))
for attempt in solution.diagnostics.get("backend_attempts", []):
    print(attempt.get("status"), attempt.get("mip_feasibility_tolerance"))

backend_status 是后端最后一次运行的原始状态;backend_attempts 逐次记录有效数值参数、 目标、界限、gap 和耗时。best_bound、gap、solve_time 提供单目标的便捷读取方式。 参数配置及内部策略的记录范围见求解与配置。

无值、超时与取消

未求解或模型变更后读取 .value 会抛出 RuntimeError。重新求解会清除旧值,因此应在变更或下一次求解前,将所需数值复制到业务数据结构。

本地搜索可能在序列化预算耗尽时返回 deadline,外部评价取消时返回 cancelled。CP-SAT / MathOpt 在验证前预算耗尽时返回 UNKNOWN 且无值。不要把这些状态视为不可行证明。

定位耗时阶段

路径 诊断字段 单位 / 含义
本地搜索 python_serialize_ns Python 序列化纳秒数
本地搜索 python_wire_bytes 序列化载荷字节数
本地搜索 python_expression_count 表达式数量
CP-SAT / MathOpt exact_phase_ms 各阶段耗时字典,单位毫秒
CP-SAT / MathOpt exact_total_ms 包装层总耗时,单位毫秒
CP-SAT / MathOpt 超时 termination_phase 预算终止阶段说明

诊断字段取决于执行到达的阶段。业务控制流优先依赖 feasible 和公开结果字段,不要要求每次返回都带有相同的内部统计。

常见问题

模型可以创建,为什么求解器拒绝它? 统一建模层比单个后端的表达能力更广。检查路径兼容性,尤其是非线性表达式、有限域边界和展开规模。

为什么增加一条表达式后旧值不可读? 新表达式改变模型,旧解被失效。先完成全部建模,再求解和读值。

为什么设置一秒预算后调用稍晚才返回? 预算采用协作式取消,正在执行的操作和结果清理会增加延迟。

找不到内核或 OR-Tools? 检查安装所用解释器与运行解释器一致,并按安装说明安装匹配的包和 extra。