# 结果与诊断

`solve()`、`solve_heuristic()` 和 `solve_optx()` 都返回 `Solution`。先检查是否有可行解，再读取变量和派生表达式的值。

## 安全读取结果

```python
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` | 本次求解状态；`unknown`、`deadline` 等停止状态不能单独证明模型无解 |
| `solver_name` | 求解入口标识：混合求解为 `hybrid`，启发式求解为 `heuristic`，精确求解为 `optx`；精确后端记录在 `diagnostics["backend"]` 中 |
| `diagnostics` | 路径相关的诊断字典；用 `.get()` 读取可选字段 |
| `best_bound` | 精确后端报告的目标值界限；不可用时为 `None`，须结合下方的后端说明理解 |
| `gap` | 当前由 HiGHS 提供的单目标相对间隙比值，`0.001` 表示 `0.1%`；不可用时为 `None` |
| `solve_time` | 当前由 HiGHS 提供的后端搜索秒数，包含重试；不可用时为 `None` |

`best_bound` 对最小化目标是下界，对最大化目标是上界，描述后端所求解问题的界限，不能单独作为原模型的最优性证明。
HiGHS 的数值修正可能使最终 `objectives` 与后端候选目标不同；多目标的分阶段指标通过
`diagnostics["backend_attempts"]` 查询，此时便捷属性 `best_bound` 和 `gap` 为 `None`。

CP-SAT 也可提供 `best_bound`，取最近一次后端搜索的界限；多目标时仅对应当时处理的目标，不能视为整个多目标问题的界限。
CP-SAT 当前不填充 `gap` 和 `solve_time`。混合和启发式求解当前不填充这三个便捷属性。
`solve_time` 不含模型转换与结果校验，完整调用耗时可由业务端计时。

交互式 `session.finish()` 也返回 `Solution`，当前 `solver_name` 为 `search`；与上表三个一次性入口的标识分开处理。

## OptX 的结论与后端信息

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

```python
print(solution.status, solution.feasible, solution.objectives)
print(solution.diagnostics.get("backend"))  # highs 或 cp_sat
print(solution.diagnostics.get("backend_status"))
```

`backend_status` 是后端最后一次运行的原始状态。HiGHS 通过 `backend_attempts` 逐次记录目标、界限、间隙、耗时及有效数值参数；CP-SAT 的阶段统计位于 `cp_sat`。
原始状态用于排查问题；业务代码应依据公开的 `status` 与 `feasible` 处理最终结果。参数说明见[求解与配置](../api/solve.md)。

## 无值、超时与取消

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

混合和启发式求解可能在时间耗尽时返回 `deadline`，外部评价取消时返回 `cancelled`。精确求解在没有可交付的可行解时，可能返回 `unknown` 或 `resource_limit`。这些停止状态不能视为不可行证明；只有明确返回 `infeasible` 才表示已确认模型无解。

## 定位耗时阶段

| 路径 | 诊断字段 | 单位 / 含义 |
| --- | --- | --- |
| 混合求解 | `python_serialize_ns` | Python 序列化纳秒数 |
| 混合求解 | `python_wire_bytes` | 序列化载荷字节数 |
| 混合求解 | `python_expression_count` | 表达式数量 |
| 启发式及精确求解 | `total_wall_time_s` | 本次调用累计耗时，单位秒；早期停止时可能缺失 |
| HiGHS | `backend_attempts` | 各次后端运行记录，`solve_time_s` 以秒为单位 |
| CP-SAT | `cp_sat` | 编译、原生搜索和验证等统计；耗时字段以 `_ns` 结尾，单位纳秒 |
| 各入口 | `termination_reason` | 可选的具体停止原因 |

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

## 常见问题

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

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

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

**提示求解组件不可用？** 检查安装所用解释器与运行解释器一致，并按[安装说明](../start/installation.md)安装匹配的 OptAgent wheel。HiGHS 和 CP-SAT 均已内置；源码开发环境需要重新构建对应内核。
