aps-agent/docs/round-89-optimize-cpsat-nat...

75 lines
3.9 KiB
Markdown
Raw Normal View History

# Round 89: optimize 原生 CP-SAT 求解器接入
更新时间:2026-09-16
## 1. 本轮目标
把 `OptimizeEngine` 从「选规则 + 复用 PoolEngine 物化」推进到真正的 V2 原生求解:
输入 `SchedulingProblemV2`,由 OR-Tools CP-SAT 决定资源分配与时序,输出
`SchedulingSolutionV2`,并且必须通过 APS 独立的 `SchedulingValidator`。
上游依据:`docs/round-85-optimize-integration-shape-plan.md` 第 14 节明确记着
「CP-SAT 的 V2 原生求解器仍应作为后续轮次接入,本轮不把 PoolEngine 适配器冒充为
CP-SAT 最优证明」。本轮就是那一轮。
## 2. 现状(本轮开始时的事实)
- `OptimizeEngine.solve_flex()` 只做算法选择 + provenance 标注,实际物化交给
`PoolEngine`(贪心占槽)。七种派工规则已跑通,但它们不是 CP-SAT。
- `server/engines/cp_engine.py` 是**经典轨**(operations/routings/workstations)
的 CP-SAT,不是 flex 闭环 V2 原生;`solver_process.py` 是它的子进程安全边界。
- 集成环境限制:项目 `.venv` 里的 NumPy 以 X86_V2 为基线构建,而本机 CPU
(sd-server,Family 6 Model 15)不支持该指令集,`ortools.sat.python.cp_model`
导入即失败。这与 `round-85` 记录的全量 CP/Excel 测试受限是同一个原因。
## 3. 本轮范围
### Slice 1(本轮完成)
- 新增 `server/engines/optimize_cpsat.py`:`SchedulingProblemV2 -> CpsatOutcome`,
内含解与可审计元数据(solverId/solverVersion/OR-Tools 状态/耗时/种子/规模)。
- 模型:每道工序在合格设备中选一台(`AddExactlyOne` + 可选定长区间),同设备
`AddNoOverlap`,设备日历与维保之外的时间作为阻塞区间一并进入 NoOverlap,工序链按
`predecessorActivityIds` 串行,目标为最小化总拖期。
- provenance 与 problem hash 绑定,与 `flex_version_to_solution_v2` 同一套口径。
- 新增 `tests/golden/test_optimize_cpsat_native.py`:解通过独立 V2 校验;总拖期不劣于
同口径 EDD 基线。
### Slice 2(下一轮)
- `OptimizeEngine.solve_flex` 增加 CP-SAT 算法路径(`algorithmId=optimize.cpsat`),
物化到 flex* 行,落版本、证据链,走 `/api/flex/schedule` 端到端。
- 目标函数与 PoolEngine `totalTardiness` 口径对齐(当前两者定义不同,不能直接比较)。
- 时间离散化(分钟 -> 5/15 分钟桶)、派工解热启动、缩短求解时间。
- 冻结/在制/模具寿命/班组与工装累计容量接入模型。
### 明确不做
- 不改 WorldStore 权威语义、审批门禁和审计链。
- 不新建第二套订单/资源/版本模型。
- 不声称 PoolEngine 适配器结果是 CP-SAT 最优证明。
## 4. 验收
- `pytest tests/golden/test_optimize_cpsat_native.py`:在具备可用 OR-Tools 的环境
通过;在 NumPy/OR-Tools 不可用的环境按既有策略 skip,不得 error。
- 解必须 `validate_solution(...).valid is True` 且无 hard violation。
- 现有回归不受影响:`tests/golden/test_optimize_simulation_world_pack.py`、
`tests/golden/test_optimize_engine.py`。
- 报告必须区分证据等级:代码、测试、真实运行;环境性跳过要写清原因。
## 5. 停止条件
- V2 契约无法表达所需约束,且无法通过局部兼容字段解决。
- 需要放宽校验才能让测试通过。
- 需要新增生产依赖或许可而没有明确运行环境。
## 6. Slice 1 证据(2026-09-16)
- 隔离解释器(CPython 3.11.15 + NumPy 1.26.4 + OR-Tools 9.11.4210):
`2 passed`;模拟数据包 72/72 工序全部排入、`validate_solution` valid、
总拖期 1,782,876 分钟不劣于同口径 EDD 基线。
- 项目 `.venv`:`1 skipped`(OR-Tools 因 NumPy 基线与 CPU 不兼容不可用)。
- 已知限制:`INFEASIBLE` 曾因拖期变量上界未包含「历史欠交」而误判,已修(
交期早于计划起点的部分必须计入上界);当前只做到 FEASIBLE,未证明最优。