Metadata-Version: 2.4
Name: aps-kernel
Version: 1.3.0
Summary: Deterministic CP-SAT scheduling kernel, independent schedule validator, and headless CLI — APS standard edition
Author: APS Contributors
License: MIT
Project-URL: Homepage, https://aps.zhinengti.online
Project-URL: Documentation, https://github.com/123aiot/aps/tree/main/docs
Project-URL: Source, https://github.com/123aiot/aps
Project-URL: Changelog, https://github.com/123aiot/aps/blob/main/CHANGELOG.md
Keywords: aps,scheduling,production-planning,cpsat,ortools,finite-capacity,manufacturing,aps-kernel
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Manufacturing
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: Chinese (Simplified)
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ortools>=9.10
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Dynamic: license-file

# aps-kernel — Metis 谋序（APS 标准版）

> **运筹帷幄，谋定后动** —— 同衡·谋序·同枢，智造同频。
> One Truth. One Plan. One Rhythm.

可嵌入的**确定性**排产内核：CP-SAT 精确求解、**独立复核器**、
工序-资源适配数据模型、设备槽位与班次日历、ε-约束 trade-off、headless CLI。

> **标准版 vs 专业版**：本包只含可嵌入内核（无 UI / 无服务 / 无 LLM）。
> 甘特图前端、Web 控制台、AI 编排层、多租户 RLS、审批与 IM 通道
> 属专业版（Docker 镜像 + docker compose）。

🌐 官网：https://aps.zhinengti.online
家族：Nereus 同衡（数字孪生）· Metis 谋序（智能排产）· Hermes 同枢（物流调度）

---

## ⭐ 求解能力（横向基准，非自说自话）

在 **16 个标准 FJSP 实例**（ft/la/abz/orb/swv/ta/yn，来源 `job_shop_lib` MIT，
含**文献公认最优值**）上的实测：

| 实例 | 工单×机器 | SPT 基线 | 规则链 | **CP-SAT** | 文献最优 | vs 最优 |
|---|---|---|---|---|---|---|
| ft06 | 6×6 | 94 | 92 | **55** | 55 | **+0.0% OPTIMAL** |
| ft10 | 10×10 | 1530 | 1310 | **930** | 930 | **+0.0% OPTIMAL** |
| ft20 | 20×5 | 1513 | 1565 | **1165** | 1165 | **+0.0% OPTIMAL** |
| la01-05 | 10×5 | ~1000 | ~940 | **最优** | — | **+0.0% OPTIMAL** |
| abz5/6 | 10×10 | ~1700 | ~1600 | **1234/943** | 同 | **+0.0% OPTIMAL** |
| orb01 | 10×10 | 1489 | 1631 | 1082 | 1059 | +2.2% FEASIBLE |
| swv01/02 | 20×10 | ~2100 | ~2100 | 1495/1562 | 1407/1475 | +6% FEASIBLE |
| ta01/02 | 15×15 | ~2100 | ~2040 | 1233/1248 | 1231/1244 | +0.3% FEASIBLE |
| yn1 | 20×20 | 1547 | 1509 | 944 | 884 | +6.8% FEASIBLE |

**11/16 达到文献最优**，其余为大规模实例（20 秒预算不足，已如实标 gap）。
**全部 8/8 独立复核通过。**

```bash
python benchmarks/run_standard_bench.py --time-limit 30
```

---

## 当前状态

**v1.3.0** —— 并行工序。350 tests passed

| 模块 | 状态 | 关键能力 |
|---|---|---|
| 数据模型 P0 | ✅ | 工序-资源适配、**空适配 ≠ 全设备可用**、槽位 |
| 输入校验 P0 | ✅ | 三项 P0 准则 + 5 类检查 |
| 规则引擎 P1 | ✅ | **7 条规则**（CR/EDD/SPT/WKWR/ATC/加权优先级/**FIFO**）+ 8 条链 |
| 日历与齐套 P2 | ✅ | 三日历求交、**班次×资源×位置**、工单级齐套布尔判定 |
| 换型规则链 P2 | ✅ | frePPLe 语义、**无匹配 = 硬约束禁止**、参数配置化 |
| CP-SAT 求解 P3 | ✅ | **字典序三级目标**、容量池用 `AddCumulative`、冻结窗口 |
| 独立复核器 P4 | ✅ | **9 项真检查**（含日历可行、模具互斥）、用输入重算不信任求解器 |
| Provenance P4 | ✅ | 快照 hash + 配置/源码/求解器版本 |
| CLI + 基准 P5 | ✅ | `solve` / `benchmark` / `explain` / `chains` |
| 冲突诊断 | ✅ | `aps explain` —— 最小冲突集 + 排不下原因 |
| ε-约束 trade-off | ✅ | 钉住交期预算，问 makespan 能压到多少 |
| **数据体检** | ✅ | `aps health` —— 四张底账逐项核对 + 可执行率估计 |
| **设备负载均衡旋钮** | ✅ | ε-约束第 3 个旋钮：钉住设备负荷不均衡度 |
| **工装模具约束** | ✅ | 跨设备 NoOverlap —— 冲压/注塑的头号约束，「机床等模具」不再是隐患 |
| **并行工序** | ✅ | 同 `seq` 的工序可同时执行（双人工位装配 / 多工位并行检测）|

---

## 三个设计立场

### 1. 诚实高于漂亮

`OPTIMAL` 只在**真正证明最优**时才标；`FEASIBLE` 必带真实 gap；
超时回退贪心解时 `diagnostics["solver_fallback"]` 明确标注来源；
**全部未排时标 `INFEASIBLE` 而非 `OPTIMAL`**（避免"看起来排好了"）。

> 这直接对应论文《Formalize, Don't Optimize》的三个统计口径：
> **返回结果率 / 验证通过率 / 已返回中通过比例** —— 分母不同，不可混比。

### 2. 复核器是必需品，不是锦上添花

`validator.independent_validate()` 用**输入数据重算**（时长、槽位、日历、
换型、设备资格），**不信任求解结果自报的值**。这不是防御性冗余 ——

> 开发中它抓到过**槽位重叠 48 处而求解器报 `OPTIMAL`**、
> **makespan = 2.3e18 的垃圾值**（`UNKNOWN` 时仍读未赋值变量）。

### 3. 基准必须公平

所有基线必须在**相同约束集**下比较。曾实现一个无视日历/工序先后的 SPT 基线，
得出「SPT 比 CP-SAT 还优」的**颠倒结论**（vsSPT = -203%）。

> 非法基线比没有基线更糟 —— 它会得出完全相反的结论。

---

## 🏗 分层架构：本包的位置

博客园《CP-SAT 排产、排程、排班》：

> 「APS（长周期规划）+ RTS/RTD（实时派工）**双层架构是业界最佳实践**」
> 「前一天做的排程，第二天全乱套」—— 排程 ≠ 派工 是经典误区

```
┌─────────────────────────────────────────────────┐
│  上层（aps-platform / 本包之外）                  │
│  · MRP / 采购 / 库存                              │
│  · APS 长周期计划（天/周）                        │
│  · RTS / RTD 实时派工（分钟级）  ← 不在本包        │
│  · MES 执行回写 / 甘特图 UI                       │
└─────────────────────────────────────────────────┘
                ↕ ScheduleInput / ScheduleResult
┌─────────────────────────────────────────────────┐
│  aps-kernel（本包）—— 求解内核，不含流程            │
│  ✅ 数据模型 / 输入校验                            │
│  ✅ 规则引擎（7 规则 + 8 链）                     │
│  ✅ CP-SAT 精确求解 + 贪心兜底                    │
│  ✅ 冻结窗口（支持增量重排）                      │
│  ✅ 独立复核器（8 项）                            │
│  ✅ ε-约束 trade-off / 冲突诊断 / 基准            │
│  ❌ 不做派工、不做 UI、不做持久化、不含 LLM         │
└─────────────────────────────────────────────────┘
```

⚠️ **为什么派工不在本包**：派工是**高频决策**（分钟级刷新），
需要实时状态推送与人工干预；本包是**低频决策**（计划级），
追求确定性与可审计。把两者混在一个包里会同时失去两者。

⚠️ **本包负责「证明这个计划可执行」，不负责「生成甘特图」**：

> 「排产的难点从来不是生成一个计划，而是**证明这个计划在约束下可执行**。」
> —— 《LLM 不会给你最优排产，求解器会》

---

## 版本与兼容性

| | |
|---|---|
| 当前 | **1.3.0** —— 功能优先迭代期，API 会随功能演进 |
| 含义 | ⚠️ **1.0.0 的 API 冻结承诺已于 2026-10-17 取消**，现按功能优先迭代 |
| 变更记录 | [CHANGELOG.md](CHANGELOG.md) —— 含破坏性变更与迁移动作 |

---

## 快速开始

```bash
pip install aps-kernel

# 0) ⭐ 上线前先体检（核对工时/BOM/日历/换型矩阵四张底账）
aps health input.json --bom bom.json --inventory stock.json

# 1) 看内置规则链
aps chains

# 2) 求解（贪心，快）
aps solve input.json --chain default

# 3) 求解（CP-SAT，可证 OPTIMAL）
aps solve input.json --solver cpsat --time-limit 30

# 4) 排不下时诊断原因（最小冲突集）
aps explain input.json

# 5) 基准验证（规则链 vs SPT vs CP-SAT）
aps benchmark --sizes 5,8,10 --chains default
```

> `aps health` 的退出码可直接接 CI：`0` 可上线 / `1` 需补数 / `2` 阻断。

```python
from aps_kernel import schedule, solve, CpSatOptions, independent_validate

# 贪心（快，不证明最优）
result = schedule(data, chain="default")

# CP-SAT（可证 OPTIMAL）
result, stats = solve(
    data, options=CpSatOptions(time_limit_seconds=30, workers=8),
)

# 独立复核 —— 不信任求解器自报
checks = independent_validate(data, result)
assert all(ok for _, ok, _ in checks)
```

---

## 已知局限（诚实列出）

| 局限 | 说明 |
|---|---|
| ~~`Job.due_date` 只能表达天~~ | ✅ 已修复（v0.10.0）：改为 `date | datetime` 联合类型，支持小时级交期。用 `due_offset_from_horizon()` 计算偏移（**不要**用 `.days * 1440`，会丢小时） |
| 交期需**整日或整时** | 建议传 `datetime`；传 `date` 时按当天 00:00 算，不是「当天结束」—— 与部分 APS 的约定不同，转换时请留意 |
| 大规模 gap 仍大 | 20 工单以上、30 秒预算只能到 FEASIBLE。**根因已定位**：
| 字典序前两级在「证明贪心已最优」上耗掉 27.5 秒。已加**下界剪枝**
| （贪心已达理论下界时跳过该级），n=10 改善 3.9% → 7.5%；
| n≥15 的 makespan 级本身在 30 秒内证不了最优（gap 60%+），
| 这是 CP-SAT 的固有限制（Chalmers 论文：57/100 实例可证最优） |
| 换型为**静态规则**，非序列相关 | frePPLe 语义已实现，但不支持「A→B→C 链式换型」的组合优化。真实注塑/印刷 A→B 与 B→A 的换型方差**可达 10 倍** |
| 缺**拆批合批** | 大批量拆多批（受最小批量约束）、小批量合并。涉及批量参数与交期权衡 |
| 模具**无寿命/维护周期**建模 | 现只有「同一时刻一台机」，没有「这副模还能用几次」 |
| 无持久化状态 | 每次求解无状态，冻结窗口需由调用方传入 |
| 合成 demo 交期偏宽 | demo 默认交期 = horizon+5 天 ≫ makespan → 拖期恒为 0；验证拖期逻辑需改用紧交期 |
| 体检的**可执行率是估计值** | 基于静态校验，不检查「现场是否会临时变更」。cp_sat_demo 实测 44%，本估计通常偏乐观 |

---

## 安装与依赖

- Python ≥ 3.11
- 运行时依赖：`ortools >= 9.12`、`PyYAML`
- **仅发 wheel**（`py3-none-any`），不发 sdist

## License

MIT
