7.3 KiB
排产算法 v1(已落地 · RULE)
代码:
server/engines/rule_engine.py
测试:tests/golden/test_rule_engine.py
定位:构造启发式(策略排序 + 顺排占槽),毫秒级;不是最优解求解器。
1. 输入 / 输出
| 内容 | |
|---|---|
| 输入 | 世界状态 world + EngineParams(策略、展望期、起算日、订单子集、引擎类型名;可选 deliveryBufferRatio / freezeWindowHours) |
| 写出 | DRAFT scheduleVersion、生产订单 PO、工单 WO、conflicts、版本 KPI 字段 |
| 权力 | 由工作流以 P1 调用;本引擎只改传入的内存 world |
请求的 engineType:RULE→规则引擎;CP→OR-Tools CP-SAT(见 scheduling-cp-v1.md);GA→遗传算法搜索订单顺序与可行产线;HYBRID→RULE 热启动 CP-SAT。三类高级引擎最终都复用本引擎的班次占槽与硬约束物化。
2. 主流程
① 收集待排订单项(过滤 CANCELLED/COMPLETED 订单与 COMPLETED 明细)
② 按 strategyTemplate 排序(OR-02:综合/均衡以 `-customerLevelWeight` 为第一键;交期优先仍以交期为主)
③ 创建 DRAFT 版本(版本链 parentVersionId)
④ 逐项:选产线 → 按工艺步骤拆 WO → 在班次窗内找槽(可跨天)→ 齐套检查
⑤ 版本内冲突扫描(产能/维保等只扫本版新 WO,避免历史污染)
⑥ 汇总 KPI(延期、利用率等)
与 legacy aps-frontend 的刻意偏差(已测固化):
- 容量/维保冲突只扫本版新工单
- 利用率只按本版工单统计
3. 策略模板(排序键)
| strategyTemplate | 排序逻辑(实现) |
|---|---|
DELIVERY_FIRST |
(deliveryDate, -levelWeight, priority) ≈ EDD 为主 |
FIFO |
(orderDate, -levelWeight, priority) |
CAPACITY_BALANCE |
(-levelWeight, priority, deliveryDate);选线时偏好累计占用少的线 |
CHANGEOVER_MIN |
贪心最近邻:按换型矩阵选下一单;选线偏好同族续排(SC-07) |
CAMPAIGN |
同产品交期窗口合并为战役 PO,再走换型最小化序(SC-08) |
COST_FIRST |
同 CHANGEOVER_MIN(以换型分钟为成本代理) |
其他 / COMPREHENSIVE |
(-levelWeight, priority, deliveryDate)(OR-02 客户等级权重) |
levelWeight 来自 scheduleParams.customerLevelWeights(默认 VIP=3/A=2/B=1/C=1)。
纠偏:COST_FIRST 仍不是财务成本最优;当前以 MD-06 换型矩阵分钟为代理。真成本目标待后续切片。
4. 占槽与资源
- 产线:由产品-产线关系
find_product_lines;无可用线 →NO_LINE - 工位:工序资格
find_workstation_for_operation;无 →NO_WORKSTATION - 时间:班次日历内找连续可用分钟;长工单可跨天拼接
- 展望期:默认
planningHorizonDays(种子参数 14) - 齐套:BOM vs 库存/在途逻辑;不足 →
MATERIAL_SHORTAGE(可推迟或标冲突,见代码分支)
5. 冲突类型(引擎实际产出)
| conflictType | 含义 |
|---|---|
NO_LINE |
产品无可用产线 |
NO_WORKSTATION |
工序无合格工位 |
MATERIAL_SHORTAGE |
齐套不足 |
DELAY |
相对交期延误 |
CAPACITY |
产线日产能/占用冲突 |
EQUIPMENT |
维保等设备不可用 |
前端可高亮超期/冲突;一键修复工作流未落地。
6. 明确未做(勿在对外材料写成已有)
- 工序级 CP Interval 全模型 / NSGA-II/Pareto / LNS(产线级 CP、GA 与 HYBRID 首切片已落地)
- 换型全局最优排序(当前为贪心最近邻)
- 战役可配窗口/最大批量与拆批回退
- 插单 LNS 局部修复 / 全量重排决策表(plan §9.11)
- 蒙特卡洛鲁棒性 / 参数推荐(Tornado one-at-a-time 已落地,见 SC-06)
见 roadmap.md。
Closed-loop Scheduling Kernel v1 / Contract V2
- 统一输入:Requirement、SupplyEvent、OperationActivity、Resource、日历/维保、目标与硬约束策略。
- 统一输出:ScheduledActivity、SupplyDecision、Pegging、UnscheduledRequirement、HardViolation、Assumption与 Provenance。
- 必须先通过独立 Validator 才可物化;检查工序顺序、资源重叠/能力、日历/维保、物料时间、pegging 守恒、activity identity 和源哈希漂移。
- RULE/Pool/外部 Skill 保留 V1 兼容层,但真实主路径必须映射 V2 并失败关闭。
Round 65 审计补强:多资源与确定性
OperationActivity.resourceRequirements使用ActivityResourceRequirement同时表达 EQUIPMENT / TEAM / TOOLING 候选、能力、容量单位和模具寿命消耗。ScheduledActivity.resourceAllocations记录每类资源的实际分配;缺少必需 TEAM/TOOLING、种类不匹配、能力不匹配、容量不足或模具寿命不足均为硬违规。- 设备分配沿 WORKSTATION -> LINE -> WORKSHOP -> FACTORY 父链汇总负荷;班组和模具分别计算累计容量与寿命,避免重复计费。
- 活动身份哈希纳入多资源要求;planning sourceHash 对自动生成 DRAFT 建议的技术 ID/时间去噪,但保留物料、数量、日期、供应类型和状态等业务语义。
Round 66 求解器执行隔离与失败关闭
CP/HYBRID 的优化调用采用独立进程协议 aps.solver-process.v1。父进程仍负责业务问题构造、门禁与结果物化;child 只接收可序列化的 world/entries/params,执行优化并返回带 requestId/digest、运行时身份和 success/error marker 的版本化 JSON。
父进程必须同时验证:
- 进程在 OS 级时限内完成,且 stdout/stderr 不含 fatal marker;即使 exit code 为 0,fatal marker 仍判失败。
- response 协议、requestId、摘要和 schema 与请求匹配。
- Python executable/base executable、
site.ENABLE_USER_SITE、OR-Tools/NumPy/Pandas/Protobuf 来源位于受信任 runtime prefix。 - 只有校验通过的 ordered entries 才进入父进程
materialize_schedule()。
失败语义固定为 fail-closed:CP 与 HYBRID 均返回 UNAVAILABLE,不创建 PO/WO,不产生可发布版本;HYBRID 不静默退回 RULE。timeout 必须终止完整进程树,父进程与 API 服务继续存活,业务 world 保持原子。
真实验收:复制 world.json 的 CP/HYBRID 均为 OPTIMAL、1 PO / 10 WO / 10 operationSlots、runtimeSafe=true;fatal 与 timeout 注入均满足上述失败语义。复制 MOM 数据虽然求解器为 OPTIMAL,但现有业务主数据阻断仍为 0 PO/WO、1 slot/1 conflict,这不是现场主数据完成证明。
源码 Sidecar 在 Python -I 下不会信任任意 PYTHONPATH。真实冒烟发现隔离模式会移除源码 checkout import root 后,只允许 bootstrap 已解析的 trusted source root;test_source_solver_child_entry_runs_under_isolated_python 固化该边界。现有冻结 EXE 尚未重建,因此新 --solver-child 的打包验证仍是构建后验收,不能由源码冒烟替代。
-
???? success response ????
responseDigest??????/????????????????pipeline/status?objective/gap ? operationSlots ????????SOLVER_RESPONSE_INVALID?????? -
父进程对 success response 强制重算
responseDigest,并校验请求/响应条目完整排列、关键业务字段、pipeline/status、objective/gap 与 operationSlots 覆盖;不一致统一SOLVER_RESPONSE_INVALID,禁止物化。