@ohtaman/washi 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.ja.md +103 -421
  2. package/README.md +103 -421
  3. package/README.zh-CN.md +103 -421
  4. package/THIRD_PARTY_LICENSES.md +5 -3
  5. package/dist/browser/solvers/glpk.js +2 -2
  6. package/dist/browser/solvers/glpk.min.js +1 -1
  7. package/dist/browser/washi.js +777 -261
  8. package/dist/browser/washi.min.js +3 -3
  9. package/dist/lib/{registry-C20sxTwm.js → registry-D7TZ3Wh_.js} +88 -18
  10. package/dist/lib/solvers/glpk.js +3 -3
  11. package/dist/lib/solvers/z3.js +1 -1
  12. package/dist/lib/washi.js +864 -421
  13. package/dist/types/index.d.ts +1 -1
  14. package/dist/types/index.d.ts.map +1 -1
  15. package/dist/types/modeler/expression.d.ts +47 -26
  16. package/dist/types/modeler/expression.d.ts.map +1 -1
  17. package/dist/types/modeler/index.d.ts +2 -2
  18. package/dist/types/modeler/index.d.ts.map +1 -1
  19. package/dist/types/modeler/model.d.ts +12 -6
  20. package/dist/types/modeler/model.d.ts.map +1 -1
  21. package/dist/types/modeler/parser.d.ts +25 -5
  22. package/dist/types/modeler/parser.d.ts.map +1 -1
  23. package/dist/types/modeler/solvers/glpk/solver.d.ts.map +1 -1
  24. package/dist/types/modeler/solvers/highs/solver.d.ts.map +1 -1
  25. package/dist/types/modeler/solvers/highs/worker-client.d.ts.map +1 -1
  26. package/dist/types/modeler/solvers/types.d.ts +2 -0
  27. package/dist/types/modeler/solvers/types.d.ts.map +1 -1
  28. package/docs/examples/diet-sensitivity.md +15 -14
  29. package/docs/examples/ecommerce-coupons.md +15 -22
  30. package/docs/examples/index.md +14 -12
  31. package/docs/examples/knapsack.md +8 -7
  32. package/docs/examples/portfolio-qp.md +11 -4
  33. package/docs/examples/production.md +4 -4
  34. package/docs/examples/shift-scheduling.md +20 -7
  35. package/docs/examples/smt-security.md +16 -4
  36. package/docs/examples/transportation.md +46 -19
  37. package/docs/examples/traveling-salesperson.md +28 -44
  38. package/docs/examples/unsat-core.md +15 -5
  39. package/docs/examples/vehicle-routing.md +10 -8
  40. package/docs/getting-started/ai-agents.md +25 -14
  41. package/docs/getting-started/cross-origin.md +56 -28
  42. package/docs/getting-started/index.md +40 -69
  43. package/docs/getting-started/runtimes.md +66 -61
  44. package/docs/guide/constraints.md +46 -40
  45. package/docs/guide/decomposition.md +127 -259
  46. package/docs/guide/expressions.md +90 -39
  47. package/docs/guide/formulation-tips.md +212 -0
  48. package/docs/guide/objectives.md +7 -4
  49. package/docs/guide/unsat-core.md +18 -6
  50. package/docs/guide/variables.md +33 -38
  51. package/docs/ja/getting-started/ai-agents.md +24 -14
  52. package/docs/solvers/highs.md +27 -6
  53. package/docs/solvers/index.md +1 -1
  54. package/docs/solvers/z3.md +3 -0
  55. package/docs/zh/getting-started/ai-agents.md +24 -14
  56. package/llms-full.txt +929 -687
  57. package/llms.txt +21 -19
  58. package/package.json +3 -3
  59. package/skills/washi/SKILL.md +14 -10
package/README.zh-CN.md CHANGED
@@ -2,9 +2,9 @@
2
2
  <picture>
3
3
  <source media="(prefers-color-scheme: dark)" srcset="./assets/washi-header-dark.png">
4
4
  <source media="(prefers-color-scheme: light)" srcset="./assets/washi-header-light.png">
5
- <img alt="WaSHI - 适用于数理优化与约束编程的代数建模器 (TypeScript &amp; JavaScript)" src="./assets/washi-header-light.png" width="420" />
5
+ <img alt="WaSHI - TypeScript 数理优化建模器" src="./assets/washi-header-light.png" width="420" />
6
6
  </picture>
7
- <p><strong>适用于数理优化与约束编程的代数建模器</strong></p>
7
+ <p><strong>TypeScript 数理优化建模器</strong></p>
8
8
  <p>
9
9
  <em>线性规划 (LP) • 混合整数规划 (MIP) • 凸二次规划 (QP) • SMT逻辑约束与冲突诊断</em>
10
10
  </p>
@@ -16,512 +16,194 @@
16
16
  <p>
17
17
  <a href="https://www.npmjs.com/package/@ohtaman/washi"><img src="https://img.shields.io/npm/v/@ohtaman/washi?color=crimson&label=npm" alt="npm version" /></a>
18
18
  <a href="https://github.com/ohtaman/washi/actions/workflows/distribution.yml"><img src="https://github.com/ohtaman/washi/actions/workflows/distribution.yml/badge.svg" alt="CI Status" /></a>
19
- <a href="https://ohtaman.github.io/washi/zh/"><img src="https://img.shields.io/badge/docs-online-blue" alt="docs" /></a>
20
- <a href="https://ohtaman.github.io/washi/demo/"><img src="https://img.shields.io/badge/demo-playground-brightgreen" alt="live demo" /></a>
19
+ <a href="https://washi.ohtaman.dev/zh/"><img src="https://img.shields.io/badge/docs-online-blue" alt="docs" /></a>
20
+ <a href="https://washi.ohtaman.dev/demo/"><img src="https://img.shields.io/badge/demo-playground-brightgreen" alt="live demo" /></a>
21
21
  <a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="license" /></a>
22
22
  </p>
23
23
  </div>
24
24
 
25
25
  ---
26
26
 
27
- **WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) 是面向 TypeScript / JavaScript 的数理优化与约束编程代数建模器,受到 Python **PuLP** 和 Julia **JuMP** 的启发。你可以在应用代码中定义变量、目标函数、算术约束和逻辑约束。WaSHI 负责构建模型、转换为求解器输入,并将结果映射回变量;优化与可满足性检查由 **HiGHS**、**Z3** 和 **GLPK** 完成。
27
+ **WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) 是面向 TypeScript / JavaScript 的数理优化与约束编程代数建模器,受到 Python **PuLP** 的启发。你可以在应用代码中定义变量、目标函数和约束,并在 Node.js 或浏览器本地使用 **HiGHS**(默认)、**Z3** 或 **GLPK** 求解。
28
28
 
29
- HiGHS 是默认求解器;Z3 和 GLPK 是可选插件。软件包提供 Node.js 和浏览器分发版本,并包含 WebAssembly 资源。部署要求请参阅[浏览器使用说明](#-浏览器与-web-worker-使用指南)。
29
+ ## ✨ 核心特性
30
30
 
31
- [在线文档](https://ohtaman.github.io/washi/zh/) · [试用浏览器演示](https://ohtaman.github.io/washi/demo/) · [AI 编程助手快速参考](docs/zh/getting-started/ai-agents.md) · [Agent Skill (`SKILL.md`)](skills/washi/SKILL.md) · [示例源码与运行方法](https://github.com/ohtaman/washi/blob/main/examples/README.md) · [ESM / script / CodePen 示例](https://github.com/ohtaman/washi/blob/main/examples/distribution/README.md)
31
+ - **直观的代数语法**:通过 `` expr`30 * ${x} + 50 * ${y} <= 40` `` 与求和、点积(`sum`, `dot`)清晰编写公式与约束。
32
+ - **跨 Node.js 与浏览器本地运行**:基于 WebAssembly,无需单独部署 Python 服务或本地编译 C/C++。
33
+ - **求解器无关**:内置 **HiGHS**,支持按需加载 **Z3**、**GLPK** 插件或自定义求解器适配器。
34
+ - **可满足性判定与冲突诊断**:支持逻辑与算术约束的可满足性判定,并在模型不可行时定位矛盾约束。
35
+ - **大规模分解算法**:内置列生成法与 Benders 分解支持。
32
36
 
33
- ```ts
34
- import { Model, expr, maximize } from "@ohtaman/washi";
35
-
36
- const m = new Model("木工产品利润最大化");
37
- const x = m.integer("桌子", { lb: 0 });
38
- const y = m.integer("椅子", { lb: 0 });
39
-
40
- m.objective(maximize(expr`30 * ${x} + 50 * ${y}`));
41
- m.constraint(expr`${x} + 2 * ${y} <= 40`, "wood_limit");
42
- m.constraint(expr`2 * ${x} + ${y} <= 50`, "labor_limit");
43
-
44
- await m.solve();
45
- console.log(`生产计划: x=${x.value}, y=${y.value} (最大利润: $${m.objectiveValue})`);
46
- ```
47
-
48
- ---
49
-
50
- ## 🎯 WaSHI 提供的功能
51
-
52
- 1. **代数模型构建**:使用领域变量构造函数(`m.binary`、`m.integer`、`m.continuous`)、标签模板字面量(`expr`)、向量聚合函数(`dot`、`sum`)以及一等约束(`m.constraint`)构建优化模型。由于 JavaScript 不支持运算符重载,`` expr`...` `` 采用类似参数化 SQL 模板的方式,在解析中缀数学运算符(`+`、`-`、`*`、`^2`、`<=`、`>=`、`==`)的同时,将 `${...}` 插值直接绑定为强类型的 `Var` 或表达式对象引用,从而保留静态类型检查、IDE 重命名支持以及多维索引访问(`${flow[i][j]}`)。
53
- 2. **求解器适配器**:通过共同的建模 API 使用 HiGHS、Z3 或 GLPK,也可以[注册自己的适配器](https://github.com/ohtaman/washi/blob/main/docs/zh/solvers/custom-solver.md)。需要选择支持相应问题类型的求解器;不同求解器的能力并不相同。
54
- 3. **本地执行与 WebAssembly 分发**:使用本地求解器适配器时,可在应用内直接求解,无需单独的 Python 服务或本地 C/C++ 编译——这消除了在快速开发和交付交互式工具时的后端基础设施瓶颈,也便于在客户端直接与浏览器内 LLM(如 WebGPU / WebLLM)协同工作。浏览器部署需要包含生成的 JS、Worker 和 WASM 资源。离线使用还需要这些资源可在本地访问或已缓存。Z3 有额外的浏览器隔离要求。
55
- 4. **命名约束与冲突诊断**:通过可满足性检查(`m.check()`),可调查矛盾约束(`conflicts` / `unsatCore`)以排查不可行性原因:内置 HiGHS 分离出**弹性修复集合**(`conflicts`,恢复可行性所需松弛的约束集合),而 Z3 提取 **SMT 不可满足核心**(`unsatCore` / `conflicts`,相互矛盾的约束子集;不保证最小性)。
56
- 5. **高级分解方法编排**:利用一等分解算法(`master.solveColumnGeneration`、`master.solveBenders`),突破单体 MIP 在特定结构(下料问题、车辆路径/VRP、旅行商/TSP、两阶段设施选址规划等)上的搜索树爆炸瓶颈。结合定价子问题(Pricing)与链接约束(`sub.link(...)`)的清晰回调编排,协同对偶定价、割平面生成与整数解复原。
57
-
58
- 模型构建与转换由 WaSHI 负责。支持的问题类型、数值行为和求解时间取决于所选求解器、配置及具体问题。建模开销与求解器执行时间应分别测量;某个模型上的结果并不构成通用性能保证。
37
+ ## 📚 文档与链接
59
38
 
60
- ---
61
-
62
- ## ⚙️ 求解器适配器与支持范围
63
-
64
- | 适配器 | 引擎许可证 | 支持的问题类型 | 引擎作用 | 集成方式 |
65
- | :--- | :--- | :--- | :--- | :--- |
66
- | **[HiGHS](https://github.com/ERGO-Code/HiGHS)** | **MIT** | **LP, MIP, 凸QP** | 数值优化 | 默认内置 |
67
- | **[Z3](https://github.com/Z3Prover/z3)** (via [`z3-solver`](https://www.npmjs.com/package/z3-solver)) | **MIT** | **SMT, SAT, 逻辑, MIP** | 可满足性检查、Unsat Core、优化 | 可选插件 (`@ohtaman/washi/solvers/z3`) |
68
- | **[GLPK](https://www.gnu.org/software/glpk/)** (via [`glpk.js`](https://www.npmjs.com/package/glpk.js)) | **GPL-3.0** | **LP, MIP** | 线性与混合整数优化 | 可选插件 (`@ohtaman/washi/solvers/glpk`) |
69
- | **Mock** | **MIT** | — | 为集成测试提供模拟响应 | 内置;不实际求解模型 |
39
+ - **[在线文档](https://washi.ohtaman.dev/zh/)**:建模指南、求解器说明与运行环境配置
40
+ - **[案例展示](https://washi.ohtaman.dev/zh/showcase/) & [浏览器演示](https://washi.ohtaman.dev/demo/)**:在线体验交互式应用与浏览器建模演练场
41
+ - **[示例目录](https://washi.ohtaman.dev/zh/examples/)**:各类问题的建模示例与可运行源码([`examples/`](examples/README.md))
42
+ - **[AI 编程助手快速参考](docs/zh/getting-started/ai-agents.md) · [Agent Skill (`SKILL.md`)](skills/washi/SKILL.md) · [`llms.txt`](https://washi.ohtaman.dev/llms.txt) / [`llms-full.txt`](https://washi.ohtaman.dev/llms-full.txt)**:面向 AI 编程助手的速查指南、技能定义与机器可读文档
70
43
 
71
44
  ---
72
45
 
73
- ## 📦 安装
46
+ ## 📦 安装与快速开始
74
47
 
75
48
  ```bash
76
- # npm
77
49
  npm install @ohtaman/washi
78
50
 
79
- # pnpm
80
- pnpm add @ohtaman/washi
81
-
82
- # yarn
83
- yarn add @ohtaman/washi
51
+ # 可选求解器插件
52
+ npm install z3-solver # 用于 SMT 逻辑与冲突诊断
53
+ npm install glpk.js # 用于 GLPK 求解器 (GPL-3.0)
84
54
 
85
- # bun
86
- bun add @ohtaman/washi
87
- ```
88
-
89
- *(可选)* 若需使用 Z3 或 GLPK 求解器,可按需安装对应依赖包:
90
-
91
- ```bash
92
- npm install z3-solver # 用于 SMT 与冲突诊断
93
- npm install glpk.js # 用于 GLPK 求解器 (GPL-3.0)
94
- ```
95
-
96
- *(可选)* 面向 AI 编程助手(Claude Code、Antigravity、Cursor、Codex 等),可以通过 `skills` CLI 或随包附带的 [`skills/washi/SKILL.md`](skills/washi/SKILL.md) 引入建模与校验技能:
97
-
98
- ```bash
99
- # 通过 skills CLI (skills.sh / vercel-labs/skills) 安装
55
+ # 可选:为 AI 编程助手(Claude Code, Cursor, Codex 等)安装建模技能
100
56
  npx skills add ohtaman/washi
101
-
102
- # 或将随包附带的技能手动复制到项目中
103
- mkdir -p .agents/skills/washi
104
- cp node_modules/@ohtaman/washi/skills/washi/SKILL.md .agents/skills/washi/SKILL.md
105
57
  ```
106
58
 
107
- ---
108
-
109
- ## 🚀 快速上手指南
110
-
111
- ### 1. 多维变量、条件指示约束 (`m.indicator`) 与解验证 (`m.validateSolution`)
112
-
113
- 一行代码声明一维字典或二维变量矩阵,通过 `m.indicator()` 表达 Big-M 条件规则,结合 `onProgress` / `AbortSignal` 控制求解过程,并通过 `m.validateSolution()` 独立校验解的合法性:
114
-
115
59
  ```ts
116
- import { Model, expr } from "@ohtaman/washi";
117
-
118
- const m = new Model("FacilityPlanning");
119
-
120
- // 1D 字典形式的二元变量
121
- const openCity = m.binary(["Tokyo", "Osaka", "Nagoya"]);
122
-
123
- // 2D 运输量矩阵: [工厂] x [门店]
124
- const flow = m.continuous(["F1", "F2"], ["StoreA", "StoreB"], { lb: 0, ub: 1000 });
125
-
126
- // 2D 网格坐标 (例如 8x8 棋盘)
127
- const board = m.binary(8, 8, { prefix: "queen" });
128
-
129
- // Big-M 条件约束: 若工厂关闭 (openCity['Tokyo'] == 0),则 flow <= 0
130
- // (省略 M 时,WaSHI 会根据变量的有限上下界自动推导紧凑安全的 Big-M)
131
- m.indicator(openCity["Tokyo"], expr`${flow["F1"]["StoreA"]} <= 0`, {
132
- activeValue: 0,
133
- name: "tokyo_closed_no_flow",
134
- });
135
-
136
- // 支持实时进度回调 (onProgress) 与 AbortSignal 取消
137
- const controller = new AbortController();
138
- await m.solve({
139
- signal: controller.signal,
140
- onProgress: (ev) => {
141
- // 实时指标: ev.elapsedTime, ev.objectiveValue, ev.objectiveBound, ev.mipGap
142
- },
143
- });
144
-
145
- // 独立校验变量边界、整数性以及线性/逻辑约束
146
- const report = m.validateSolution();
147
- console.log("解验证通过?", report.valid);
148
- ```
149
-
150
- ---
151
-
152
- ### 2. 投资组合风险最小化 (凸二次规划: QP)
60
+ import { Model, expr, maximize } from "@ohtaman/washi";
153
61
 
154
- 在满足预期收益与预算约束的前提下,基于协方差矩阵最小化投资组合风险:
62
+ const m = new Model("木工产品利润最大化");
63
+ const x = m.integer("桌子", { lb: 0 });
64
+ const y = m.integer("椅子", { lb: 0 });
155
65
 
156
- ```ts
157
- import { Model, QuadExpr, sum, dot, minimize, expr } from "@ohtaman/washi";
158
-
159
- const m = new Model("MarkowitzPortfolio");
160
- const assets = ["Tech", "Bonds", "RealEstate"];
161
- const returns = [0.14, 0.04, 0.08];
162
-
163
- // 决策变量: 各资产投资权重 (0.0 ~ 1.0)
164
- const w = m.continuous(assets, { lb: 0, ub: 1 });
165
-
166
- // 1. 预算约束: 资金分配总额 100%
167
- m.constraint(expr`${sum(assets, (a) => w[a])} == 1.0`, "budget");
168
-
169
- // 2. 目标回报率: 组合最低回报率 >= 8.5%
170
- const retMap = Object.fromEntries(assets.map((a, i) => [a, returns[i]]));
171
- m.constraint(expr`${dot(retMap, w)} >= 0.085`, "min_return");
172
-
173
- // 3. 资产协方差矩阵 (风险与相关性)
174
- const cov = [
175
- [0.040, 0.002, 0.015],
176
- [0.002, 0.005, 0.002],
177
- [0.015, 0.002, 0.025],
178
- ];
179
-
180
- // 二次目标函数: w^T * Cov * w
181
- let risk = new QuadExpr();
182
- for (let i = 0; i < assets.length; i++) {
183
- for (let j = 0; j < assets.length; j++) {
184
- risk = risk.add(w[assets[i]].mul(w[assets[j]]).mul(cov[i][j]));
185
- }
186
- }
187
- m.objective(minimize(risk));
66
+ m.objective(maximize(expr`30 * ${x} + 50 * ${y}`));
67
+ m.constraint(expr`${x} + 2 * ${y} <= 40`, "wood_limit");
68
+ m.constraint(expr`2 * ${x} + ${y} <= 50`, "labor_limit");
188
69
 
189
70
  await m.solve();
190
- console.log(`最小方差: ${m.objectiveValue?.toFixed(6)}`);
191
- assets.forEach((name) => {
192
- console.log(` ${name}: ${((w[name].value || 0) * 100).toFixed(2)}%`);
193
- });
194
- ```
195
-
196
- ---
197
-
198
- ### 3. SMT 逻辑与规则引擎 (集成 Z3)
199
-
200
- 原生支持布尔命题变量(`BoolVar`)、逻辑连接词(`and`, `or`, `implies`, `not`, `xor`)与数值算术约束的混合表达:
201
-
202
- ```ts
203
- import { Model, not, expr } from "@ohtaman/washi";
204
- import "@ohtaman/washi/solvers/z3";
205
-
206
- const m = new Model({ name: "SmartSecurityRules" });
207
-
208
- const isNight = m.bool("isNight");
209
- const motion = m.bool("motion");
210
- const alarm = m.bool("alarm");
211
- const siren = m.bool("siren");
212
- const lux = m.integer("lux", { lb: 0 });
213
-
214
- // 规则定义
215
- m.constraint(lux.le(50).implies(isNight), "dark_implies_night");
216
- m.constraint(motion.and(isNight).and(alarm).implies(siren), "alarm_rule");
217
-
218
- // 传感器当前输入数据
219
- m.constraint(expr`${lux} <= 10`, "sensor_dark");
220
- m.constraint(motion, "sensor_motion");
221
- m.constraint(alarm, "alarm_on");
222
-
223
- // 无目标函数直接判定可满足性 (SAT)
224
- const res = await m.check({ solver: "z3" });
225
-
226
- console.log(`系统状态满足? ${res.status === "Sat"}`); // true
227
- console.log(`警报响起? ${m.values.get("siren")}`); // true
71
+ console.log(`生产计划: x=${x.value}, y=${y.value} (最大利润: $${m.objectiveValue})`);
228
72
  ```
229
73
 
230
74
  ---
231
75
 
232
- ### 4. 冲突诊断 (`conflicts` / `unsatCore`)
233
-
234
- 当规则或约束之间存在矛盾时,可定位不可行根因以采取干预措施:
235
- - **内置 HiGHS 与 GLPK**:`await m.check()` 采用单次求解弹性松弛模型($\min \sum s_i$),无需安装外部求解器即可定位 `res.conflicts`——即恢复可行性所需松弛的**修复集合**。
236
- - **Z3**:`await m.check({ solver: "z3" })` 提供精确的 SMT **不可满足核心(Unsat Core)** 提取(`res.unsatCore` 与 `res.conflicts`),返回相互矛盾的约束子集。
237
-
238
- ```ts
239
- import { Model, expr } from "@ohtaman/washi";
240
-
241
- const m = new Model("ConflictDiagnosis");
242
- const engineers = m.integer("engineers", { lb: 0, ub: 20 });
243
- const budget = m.continuous("budget", { lb: 0, ub: 100000 });
244
- const rushDelivery = m.bool("rushDelivery");
245
-
246
- // 规则 1: 每位工程师成本 $8,000
247
- m.constraint(expr`8000 * ${engineers} <= ${budget}`, "budget_limit");
248
-
249
- // 规则 2: 客户要求加急交付
250
- m.constraint(rushDelivery, "rush_required");
251
-
252
- // 规则 3: 加急交付需至少配备 8 名工程师
253
- m.constraint(rushDelivery.implies(engineers.ge(8)), "rush_staffing_rule");
254
-
255
- // 规则 4: 董事会严格预算上限 $50,000 (冲突点: 8人 * $8,000 = $64,000 > $50,000!)
256
- m.constraint(expr`${budget} <= 50000`, "strict_board_budget_cap");
257
-
258
- // 规则 5: 最低 1 名员工用工底线(无关规则)
259
- m.constraint(expr`${engineers} >= 1`, "minimum_one_employee");
76
+ ## ⚙️ 求解器概览
260
77
 
261
- // 1. 使用默认 HiGHS 进行弹性修复诊断
262
- const res = await m.check();
263
-
264
- console.log(`求解状态: ${res.status}`); // "Unsat"
265
- console.log("修复约束集合(需松弛的约束):", res.conflicts);
266
- // HiGHS 输出: ["rush_required"]
267
- // (松弛 rush_required 即可恢复可行性;无关的 minimum_one_employee 不受影响)
78
+ | 求解器 | 许可证 | 支持问题类型 | 主要用途 | 引入方式 |
79
+ | :--- | :--- | :--- | :--- | :--- |
80
+ | **[HiGHS](https://github.com/ERGO-Code/HiGHS)** | MIT | LP, MIP, 凸QP | 数值优化与弹性冲突修复诊断 | 默认内置 |
81
+ | **[Z3](https://github.com/Z3Prover/z3)** | MIT | SMT, SAT, 逻辑, MIP | 逻辑规则、可满足性判定与精确 `unsatCore` | `import "@ohtaman/washi/solvers/z3"` |
82
+ | **[GLPK](https://www.gnu.org/software/glpk/)** | GPL-3.0 | LP, MIP | 线性与混合整数规划 | `import "@ohtaman/washi/solvers/glpk"` |
83
+ | **Mock** | MIT | — | 单元与集成测试模拟响应 | 内置 (`MockSolver`) |
268
84
 
269
- // 2. 或使用 Z3 提取精确 SMT 不可满足核心(需导入 "@ohtaman/washi/solvers/z3")
270
- // const z3Res = await m.check({ solver: "z3" });
271
- // console.log("相互矛盾核心:", z3Res.unsatCore);
272
- // Z3 输出: ["budget_limit", "rush_required", "rush_staffing_rule", "strict_board_budget_cap"]
273
- ```
85
+ 导入对应插件后,可在 `new Model(...)`、`m.solve(...)` 或 `m.check(...)` 中传入 `{ solver: "z3" }` 或 `{ solver: "glpk" }`。
274
86
 
275
87
  ---
276
88
 
277
- ### 5. 使用 GLPK 求解器 (GPL-3.0)
278
-
279
- 使用 GNU Linear Programming Kit (GLPK) 求解器插件:
280
-
281
- ```ts
282
- import { Model, expr, maximize } from "@ohtaman/washi";
283
- import "@ohtaman/washi/solvers/glpk";
89
+ ## 🚀 常用用法示例
284
90
 
285
- const m = new Model({ solver: "glpk" });
286
- const x = m.integer("x", { lb: 0 });
287
- const y = m.integer("y", { lb: 0 });
91
+ ### 1. 求和、点积(`sum` / `dot`)与条件约束
288
92
 
289
- m.objective(maximize(expr`30 * ${x} + 50 * ${y}`));
290
- m.constraint(expr`${x} + 2 * ${y} <= 40`, "wood_limit");
291
- m.constraint(expr`2 * ${x} + ${y} <= 50`, "labor_limit");
292
-
293
- const status = await m.solve();
294
- console.log(`求解状态: ${status}`); // "Optimal"
295
- console.log(`目标函数值: ${m.objectiveValue}`); // 1100
296
- ```
297
-
298
- ---
299
-
300
- ### 6. 向量运算与高效点积 (`dot`)
301
-
302
- 无需嵌套循环,一行代码完成一维和二维变量的线性组合:
93
+ 使用 `dot` / `sum` 组合线性表达式,并通过 `m.indicator()` 表达条件规则:
303
94
 
304
95
  ```ts
305
- import { Model, dot, minimize } from "@ohtaman/washi";
96
+ import { Model, expr, minimize } from "@ohtaman/washi";
306
97
 
307
- const m = new Model();
98
+ const m = new Model("TransportPlanning");
308
99
  const factories = ["Tokyo", "Osaka"];
309
100
  const stores = ["StoreA", "StoreB"];
310
-
311
101
  const costs = {
312
102
  Tokyo: { StoreA: 4, StoreB: 7 },
313
103
  Osaka: { StoreA: 8, StoreB: 3 },
314
104
  };
315
105
 
316
- const ship = m.continuous(factories, stores);
106
+ const open = m.binary(factories);
107
+ const ship = m.continuous(factories, stores, { lb: 0, ub: 500 });
317
108
 
318
- // 一行代码最小化总运输成本:
319
- m.objective(minimize(dot(costs, ship)));
109
+ // 若东京工厂关闭 (open["Tokyo"] == 0),从东京工厂发出的总运输量必须为 0
110
+ m.indicator(open["Tokyo"], expr`sum(${ship["Tokyo"]}) <= 0`, { activeValue: 0 });
111
+ m.constraint(expr`${ship["Tokyo"]["StoreA"]} + ${ship["Osaka"]["StoreA"]} >= 100`, "demand_A");
112
+
113
+ m.objective(minimize(expr`dot(${costs}, ${ship})`));
320
114
  await m.solve();
321
115
 
322
- // 获取所有变量的最优取值结构
323
- const solution = m.getValues(ship);
324
- console.log(solution);
116
+ console.log("Tokyo -> StoreA:", ship["Tokyo"]["StoreA"].value);
325
117
  ```
326
118
 
327
- ---
119
+ ### 2. 凸二次规划 (QP)
328
120
 
329
- ## 🌐 浏览器与 Web Worker 使用指南
121
+ 在线性约束下最小化二次目标函数:
330
122
 
331
- HiGHS 默认使用包内的 WASM,**不会自动回退到 CDN**。Node.js 使用已安装的 HiGHS;Vite / webpack 5 可以根据包内的 WASM 和 Worker 引用生成部署文件。
123
+ ```ts
124
+ import { Model, expr, minimize } from "@ohtaman/washi";
332
125
 
333
- ### npm 与构建工具
126
+ const m = new Model("PortfolioQP");
127
+ const x = m.continuous("tech", { lb: 0, ub: 1 });
128
+ const y = m.continuous("bonds", { lb: 0, ub: 1 });
334
129
 
335
- ```typescript
336
- import { Model } from "@ohtaman/washi";
337
- const model = new Model();
338
- // 定义变量、目标函数和约束
339
- await model.solve();
340
- ```
130
+ m.constraint(expr`${x} + ${y} == 1`, "budget");
131
+ m.constraint(expr`0.14 * ${x} + 0.04 * ${y} >= 0.08`, "min_return");
132
+ m.objective(minimize(expr`0.04 * ${x}^2 + 0.005 * ${y}^2`));
341
133
 
342
- 在验证的 Vite / webpack 构建中,不需要手动复制 WASM 或配置 URL。其他构建工具及 SSR 需要单独验证;浏览器求解应在客户端执行。浏览器默认使用 Worker。简单演示可以使用 `model.solve({ useWorker: false })`,但较长的计算会阻塞 UI。
134
+ await m.solve();
135
+ console.log(`Tech: ${x.value?.toFixed(2)}, Bonds: ${y.value?.toFixed(2)}`);
136
+ ```
343
137
 
344
- ### 浏览器原生 ESM(无需应用构建)
138
+ ### 3. SMT 逻辑规则与冲突诊断 (`m.check`)
345
139
 
346
- 通过 HTTP 提供整个 `dist/browser` 目录,包括 JS 分块、`highs.wasm` 和 Worker。不需要 Import Maps。
140
+ 表达逻辑蕴含规则并排查不可行原因:
141
+ - **HiGHS(默认)**:提取**弹性修复集合**(`res.conflicts`),即松弛后可恢复可行性的约束。
142
+ - **Z3**:提取精确的 **SMT 不可满足核心**(`res.unsatCore` / `res.conflicts`),即相互矛盾的约束子集。
347
143
 
348
- ```html
349
- <script type="module">
350
- import { Model } from "./washi/washi.js";
351
- const model = new Model();
352
- // 定义变量、目标函数和约束
353
- await model.solve({ useWorker: false });
354
- </script>
355
- ```
144
+ ```ts
145
+ import { Model, implies, expr } from "@ohtaman/washi";
146
+ // import "@ohtaman/washi/solvers/z3"; // 可选:使用 Z3 提取精确 SMT unsatCore
356
147
 
357
- ### 普通 script / CodePen
148
+ const m = new Model("StaffingRules");
149
+ const engineers = m.integer("engineers", { lb: 0, ub: 20 });
150
+ const budget = m.continuous("budget", { lb: 0, ub: 100000 });
151
+ const rush = m.bool("rush");
358
152
 
359
- `dist/browser/washi.min.js` 导出全局 API `Washi`。将其 URL 添加到 CodePen 的 External Scripts,或使用:
153
+ m.constraint(expr`8000 * ${engineers} <= ${budget}`, "budget_limit");
154
+ m.constraint(rush, "rush_required");
155
+ m.constraint(implies(rush, expr`${engineers} >= 8`), "rush_staffing");
156
+ m.constraint(expr`${budget} <= 50000`, "budget_cap"); // 冲突: 8人 * $8,000 > $50,000
157
+ m.constraint(expr`${engineers} >= 1`, "min_staff"); // 无关规则
360
158
 
361
- ```html
362
- <script src="./washi/washi.min.js"></script>
363
- <script>
364
- const model = new Washi.Model();
365
- // 定义变量、目标函数和约束
366
- model.solve({ useWorker: false }).then(status => console.log(status));
367
- </script>
159
+ const res = await m.check(); // 或 await m.check({ solver: "z3" })
160
+ console.log(res.status); // "Unsat"
161
+ console.log(res.conflicts); // HiGHS: ["rush_required"]
368
162
  ```
369
163
 
370
- 若通过 CDN 加载,可使用 `https://cdn.jsdelivr.net/npm/@ohtaman/washi@<version>/dist/browser/washi.min.js`(待包含相应 API 的版本发布后指定该版本号)。ESM 使用同版本的 `dist/browser/washi.js`。选择 CDN URL 就是显式使用 CDN;本地部署不会自动改用外部 CDN。
164
+ ---
371
165
 
372
- ### 浏览器环境中的求解器插件(GLPK & Z3)
166
+ ## 🌐 浏览器与 Web Worker 使用指南
373
167
 
374
- 浏览器发布包在 `dist/browser/solvers/` 下提供了开箱即用的独立求解器插件:
375
- - **GLPK**: `dist/browser/solvers/glpk.js` (ESM) 与 `dist/browser/solvers/glpk.min.js` (IIFE,挂载全局 `WashiGLPK`)
376
- - **Z3**: `dist/browser/solvers/z3.js` (ESM) 与 `dist/browser/solvers/z3.min.js` (IIFE,挂载全局 `WashiZ3`),附带 `z3-built.js` 和 `z3-built.wasm`
168
+ - **打包工具 (Vite / webpack 5)**:直接 `import { Model } from "@ohtaman/washi"` 即可。浏览器默认在 Web Worker 中求解;传入 `{ useWorker: false }` 可在主线程执行。
169
+ - **原生 ESM / Script 标签 / CDN**:部署 `dist/browser/` 目录(含 `highs.wasm` 与 Worker 资源)或从 CDN 加载。
377
170
 
378
- #### 浏览器 ESM 使用 GLPK
379
171
  ```html
172
+ <!-- 浏览器原生 ESM -->
380
173
  <script type="module">
381
- import { Model, maximize } from "./washi/washi.js";
382
- import "./washi/solvers/glpk.js";
383
-
384
- const model = new Model({ solver: "glpk" });
385
- const x = model.continuous("x", { lb: 0, ub: 10 });
386
- model.objective(maximize(x));
387
- await model.solve();
388
- console.log("GLPK 求解状态:", model.status);
174
+ import { Model } from "./washi/washi.js";
175
+ // 可选求解器插件: import "./washi/solvers/glpk.js" 或 "./washi/solvers/z3.js"
176
+ const m = new Model();
177
+ await m.solve();
389
178
  </script>
390
- ```
391
179
 
392
- #### 原生脚本标签使用 GLPK
393
- ```html
394
- <script src="./washi/washi.min.js"></script>
395
- <script src="./washi/solvers/glpk.min.js"></script>
396
- <script>
397
- const model = new Washi.Model({ solver: "glpk" });
398
- const x = model.continuous("x", { lb: 0, ub: 10 });
399
- model.objective(Washi.maximize(x));
400
- model.solve().then(status => console.log("GLPK 求解状态:", status));
401
- </script>
180
+ <!-- Script 标签 / CodePen (挂载全局变量 Washi) -->
181
+ <script src="https://cdn.jsdelivr.net/npm/@ohtaman/washi/dist/browser/washi.min.js"></script>
402
182
  ```
403
183
 
404
184
  > [!NOTE]
405
- > **浏览器环境中使用 Z3 的配置要求与跨源隔离**:
406
- > 由于 Z3 的 WebAssembly 引擎依托多线程 (`SharedArrayBuffer`),现代浏览器强制要求跨源隔离(`Cross-Origin-Opener-Policy: same-origin` 与 `Cross-Origin-Embedder-Policy: require-corp`)。关于静态托管(`coi-serviceworker.js`)、离线/内网部署、CSP(`worker-src blob:`)与自定义 WASM URL(`setHighsWasmUrl`)的完整说明,请参阅 [跨源隔离指南](docs/zh/getting-started/cross-origin.md) 与 [运行时环境配置](docs/zh/getting-started/runtimes.md)。
407
-
408
- 完整独立的 ESM、Script 标签与 CodePen 示例请参阅 [`examples/distribution/`](examples/distribution/README.md)。
185
+ > **浏览器中使用 Z3**:Z3 的 WebAssembly 引擎依赖 `SharedArrayBuffer`,需要配置跨源隔离响应头(`COOP: same-origin` 与 `COEP: require-corp`)。详见[跨源隔离指南](docs/zh/getting-started/cross-origin.md)与 [`examples/distribution/`](examples/distribution/README.md)。
409
186
 
410
187
  ---
411
188
 
412
- ## 🛠️ 自定义求解器开发与架构扩展
413
-
414
- WaSHI 采用完全解耦的插件式求解器架构。你可以轻松编写并注册自定义求解器适配器(如云端 REST 求解服务、定制 WebAssembly 引擎或商业求解器):
189
+ ## 🤝 参与开发与贡献
415
190
 
416
- - 完整开发指南、接口契约(`Solver`, `SolveModelData`, `CheckModelData`, `SolverResult`)与测试实践详见 [自定义求解器开发指南](docs/zh/solvers/custom-solver.md)。
191
+ 关于本地开发、运行测试与基准测试、重新构建 WebAssembly 资源以及发布流程,请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。
417
192
 
418
193
  ---
419
194
 
420
- ## 📚 文档指南
195
+ ## 🙏 致谢
421
196
 
422
- 完整文档可在 **[ohtaman.github.io/washi/zh/](https://ohtaman.github.io/washi/zh/)** 及仓库的 [`docs/zh/`](docs/zh/)([英文版 `docs/`](docs/))中查阅:
197
+ WaSHI 的诞生离不开数理优化与自动推理开源社区的卓越工作:
423
198
 
424
- - **快速上手**: [快速开始](docs/zh/getting-started/index.md) · [AI 编程助手快速参考](docs/zh/getting-started/ai-agents.md) · [运行时环境配置](docs/zh/getting-started/runtimes.md) · [跨源隔离指南 (Z3)](docs/zh/getting-started/cross-origin.md)
425
- - **建模指南**: [决策变量 (`Var`, `BoolVar`)](docs/zh/guide/variables.md) · [表达式与聚合 (`expr`, `sum`, `dot`)](docs/zh/guide/expressions.md) · [约束与逻辑条件 (`indicator`, SMT)](docs/zh/guide/constraints.md) · [目标函数与求解 (`solve`, `validateSolution`)](docs/zh/guide/objectives.md) · [可满足性与 Unsat Core (`check`)](docs/zh/guide/unsat-core.md) · [分解法 (`solveColumnGeneration`, `solveBenders`)](docs/zh/guide/decomposition.md)
426
- - **求解器**: [求解器概览](docs/zh/solvers/index.md) · [HiGHS](docs/zh/solvers/highs.md) · [Z3](docs/zh/solvers/z3.md) · [GLPK](docs/zh/solvers/glpk.md) · [自定义求解器](docs/zh/solvers/custom-solver.md)
427
-
428
- ---
429
-
430
- ## 💻 示例与浏览器演示
431
-
432
- [示例目录](https://github.com/ohtaman/washi/blob/main/examples/README.md)与[在线案例与 API 索引](https://ohtaman.github.io/washi/zh/examples/)按问题类别和 WaSHI API 功能汇总了源码链接及本地运行方法。
433
-
434
- | 类别 | 示例 | 展示内容 | 求解器 |
435
- | :--- | :--- | :--- | :--- |
436
- | **基础模型** | [生产计划](https://github.com/ohtaman/washi/blob/main/examples/node/01-production-planning.ts) | 整数变量、利润目标与资源约束 (`expr`) | HiGHS |
437
- | **基础模型** | [运输与分配网络](https://github.com/ohtaman/washi/blob/main/examples/node/09-transportation-problem.ts) | 二维矩阵变量 (`continuous(rows, cols)`) 与供需平衡 | HiGHS |
438
- | **基础模型** | [营养问题与灵敏度分析](https://github.com/ohtaman/washi/blob/main/examples/node/10-diet-sensitivity.ts) | 影子价格 (`constr.dual`)、松弛量 (`constr.slack`) 与缩减成本 (`var.reducedCost`) | HiGHS |
439
- | **实战应用** | [员工排班与冲突诊断](https://github.com/ohtaman/washi/blob/main/examples/node/11-shift-scheduling.ts) | 周排班优化与周六休假冲突诊断 | HiGHS + Z3 |
440
- | **实战应用** | [购物车优惠券最优组合](https://github.com/ohtaman/washi/blob/main/examples/node/12-ecommerce-coupon-optimizer.ts) | 满减门槛条件约束 (`indicator`)、互斥规则与凑单推荐 | HiGHS |
441
- | **大规模分解** | [车辆路径规划 (CVRP)](https://github.com/ohtaman/washi/blob/main/examples/node/13-vehicle-routing-column-generation.ts) | 列生成法 (Dantzig-Wolfe): 基于对偶影子价格动态定价可行配送路线 | HiGHS |
442
- | **大规模分解** | [旅行商问题 (TSP)](https://github.com/ohtaman/washi/blob/main/examples/node/14-traveling-salesperson-benders.ts) | Benders 分解 (DFJ 法): 通过可行性割平面延迟生成子回路消除约束 | HiGHS |
443
- | **实战应用** | [投资组合分配](https://github.com/ohtaman/washi/blob/main/examples/node/03-portfolio-qp.ts) | 凸二次目标函数 (`QuadExpr`) 与分配约束 | HiGHS |
444
- | **逻辑 / SMT** | [业务规则检查](https://github.com/ohtaman/washi/blob/main/examples/node/04-smt-security-rules.ts) | 算术与逻辑约束 (`bool`, `implies`) 的可满足性检查 | Z3 |
445
- | **逻辑 / SMT** | [冲突诊断](https://github.com/ohtaman/washi/blob/main/examples/node/05-unsat-core-diagnosis.ts) | 命名约束与 Unsat Core (`unsatCore`) | Z3 |
446
-
447
- 在[在线浏览器演示](https://ohtaman.github.io/washi/demo/)中可以编辑并运行模型。浏览器 ESM、script 标签和 CodePen 的用法请参阅[分发示例](https://github.com/ohtaman/washi/blob/main/examples/distribution/README.md)。Z3 需要跨源隔离;具体要求见上方浏览器说明。
448
-
449
- 本地运行前,请克隆仓库并安装开发依赖:
450
-
451
- ```bash
452
- git clone https://github.com/ohtaman/washi.git
453
- cd washi
454
- npm ci
455
- npx tsx examples/node/01-production-planning.ts
456
- npx tsx examples/node/09-transportation-problem.ts
457
- npx tsx examples/node/10-diet-sensitivity.ts
458
- npx tsx examples/node/11-shift-scheduling.ts
459
- npx tsx examples/node/12-ecommerce-coupon-optimizer.ts
460
- npx tsx examples/node/13-vehicle-routing-column-generation.ts
461
- npx tsx examples/node/14-traveling-salesperson-benders.ts
462
-
463
- # 本地浏览器演示: http://localhost:5173/demo/
464
- npm run dev
465
- ```
466
-
467
- 示例导入仓库的 `src/` 模块。使用已发布软件包的应用应改为导入 `@ohtaman/washi` 及所需的求解器插件。
468
-
469
- ---
470
-
471
- ## 🧪 自动化测试与可复现基准测试
472
-
473
- 运行仓库的单元测试与集成测试,并构建分发版本:
474
-
475
- ```bash
476
- # 运行全部单元与集成测试
477
- npm test
478
-
479
- # 构建生产级依赖包与 TypeScript 类型定义
480
- npm run build
481
- ```
482
-
483
- ### 可选的可复现基准测试
484
-
485
- 在不将耗时阈值混入正确性测试断言的前提下,对确定性的 `small-lp`(24 个变量、18 条约束)和 `scheduling-mip`(315 个变量、231 条约束,含重建模型的 `initialValue` 热启动)进行分阶段性能测量:
486
-
487
- ```bash
488
- # 运行 Node.js 进程内 WASM 基准测试(HiGHS 与 GLPK,默认 5 次热重复)
489
- npm run bench
490
-
491
- # 自定义重复次数或输出 JSON
492
- node scripts/run-benchmarks.mjs --iterations=10 --json
493
-
494
- # 同时测量无头 Chromium Web Worker 执行(需要安装 Playwright Chromium)
495
- node scripts/run-benchmarks.mjs --browser
496
- ```
497
-
498
- - **明确的测量边界**:将冷启动初始化(`coldRuntimeInitMs`、`coldFirstSolveMs`)与复用运行时的重复测量(`modelBuildMs`、`validationMs`、LP 字符串适配器的 `lpSerializationMs` 或结构化适配器的 `symbolMapMs`、基于 `MockSolver` 的 `resultMappingMs`、`adapterSolveMs` 以及 `endToEndSolveMs`)分开直接测量,不通过相减来臆造“原生求解器时间”。
499
- - **区分不同执行环境**:Node.js 进程内 WASM(`usesBrowserWorker: false`)与浏览器 Web Worker 执行(`usesBrowserWorker: true`,包含 Worker 生命周期与 `postMessage` 结构化克隆传输)作为不同执行环境分别报告,不可直接互换作基线。
500
-
501
- ### HiGHS WebAssembly 重新构建与发布流程
502
-
503
- 1. **更新 / 重新构建 HiGHS WebAssembly 资源(`highs.config.json`)**:
504
- ```bash
505
- # 从 ERGO-Code/HiGHS 编译 public/highs.wasm 与 runtime.js,并更新 highs.config.json 中的 SHA-256 哈希
506
- npm run build:highs-wasm
507
-
508
- # 合并到 main 后,将更新后的资源覆盖上传至对应的 highs-<version> GitHub Release 标签,
509
- # 确保按需下载(scripts/ensure-highs-wasm.mjs)与 highs.config.json 的 SHA-256 校验一致:
510
- gh release upload highs-v1.15.1 public/highs.wasm src/modeler/solvers/highs/runtime.js --clobber
511
- ```
512
- (也可在 GitHub Actions 中手动触发 `.github/workflows/build-wasm.yml` 并启用 `create_release: true`,随后下载工作流产物 `highs-wasm-assets`(含 `public/highs.wasm`、`src/modeler/solvers/highs/runtime.js` 与 `highs.config.json`)并提交至仓库,以确保仓库校验和与已发布的 Release 资产保持同步。)
513
-
514
- 2. **发布 `@ohtaman/washi` 至 npm**:
515
- - 合并至 `main` 会自动通过 `.github/workflows/deploy-demo.yml` 部署文档与在线演示到 GitHub Pages,但**不会**自动发布至 npm。
516
- - 如需发布新版本至 npm,请先在 `main` 上更新 `package.json` 的 `"version"`,然后创建并发布 GitHub Release(例如 `gh release create v0.5.1 --generate-notes`)。发布 Release 会触发 `.github/workflows/publish-npm.yml`,在通过单元测试与 Playwright 分发验证后通过 OIDC Trusted Publishing 自动发布至 npm。
199
+ - **[HiGHS](https://highs.dev/)**([`ERGO-Code/HiGHS`](https://github.com/ERGO-Code/HiGHS))— 发源于爱丁堡大学、由 Julian Hall、Qi Huangfu、Ivet Galabova、Leona Gottwald、Michael Feldmeier 及社区贡献者共同打造的高性能开源 LP / MIP / 凸 QP 求解器,驱动了 WaSHI 的内置默认引擎(*Huangfu & Hall, Mathematical Programming Computation, 2018*, [DOI: 10.1007/s12532-017-0130-5](https://doi.org/10.1007/s12532-017-0130-5))。
200
+ - **[Z3 Theorem Prover](https://github.com/Z3Prover/z3)**([`z3-solver`](https://www.npmjs.com/package/z3-solver))— 由 Microsoft Research 研发,驱动了 WaSHI 可选的 SMT 可满足性判定与精确 `unsatCore` 冲突诊断插件。
201
+ - **[GLPK](https://www.gnu.org/software/glpk/) & [`glpk.js`](https://github.com/jvail/glpk.js)** — 驱动了 WaSHI 可选的 GPL-3.0 LP / MIP 求解器插件。
202
+ - **[PuLP](https://github.com/coin-or/pulp)** — 启发了 WaSHI 声明式代数建模 API 的设计。
517
203
 
518
204
  ---
519
205
 
520
206
  ## 📄 许可证
521
207
 
522
208
  - **`@ohtaman/washi`**: [MIT 许可证](./LICENSE)
523
- - **HiGHS**(默认求解器,[ERGO-Code/HiGHS](https://github.com/ERGO-Code/HiGHS)): MIT 许可证
524
- - **Z3**(可选插件,通过 [`z3-solver`](https://www.npmjs.com/package/z3-solver)): MIT 许可证
525
- - **GLPK**(可选插件,通过 [`glpk.js`](https://www.npmjs.com/package/glpk.js)): GPL-3.0 许可证
526
-
527
- 有关内置及外部求解器的完整版权声明和许可信息,请参阅 [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md)。
209
+ - **内置与可选引擎**: HiGHS (MIT)、Z3 (MIT)、GLPK (GPL-3.0)。完整许可说明请参阅 [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md)。