@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.ja.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 / 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論理制約 &amp; 矛盾診断</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/ja/"><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/ja/"><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)は、Python の **PuLP** や Julia の **JuMP** に着想を得た、数理最適化と制約プログラミングのための TypeScript / JavaScript 向け代数モデラーです。アプリケーションのコードで変数・目的関数・数値制約や論理制約を記述できます。WaSHI はモデルの構築、ソルバー向けの変換、変数への結果の反映を担当し、最適化や充足可能性の判定は **HiGHS**・**Z3**・**GLPK** が行います。
27
+ **WaSHI**(WebAssembly-backed, Solver-independent, High-level modeling Interface)は、Python の **PuLP** に着想を得た、数理最適化と制約プログラミングのための TypeScript / JavaScript 向け代数モデラーです。変数・目的関数・制約をアプリケーションコードで記述し、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/ja/) · [ブラウザデモを試す](https://ohtaman.github.io/washi/demo/) · [AIエージェント向けクイックリファレンス](docs/ja/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
+ - **充足判定と矛盾診断**: 論理・数値制約の充足可能性判定や、実行不能(Infeasible)になった原因制約の特定に対応しています。
35
+ - **大規模問題の分解法**: 列生成法やベンダーズ分解などの分解アルゴリズムをサポートしています。
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`, "木材上限");
42
- m.constraint(expr`2 * ${x} + ${y} <= 50`, "労働力上限");
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` や式のオブジェクト参照として直接バインドします。これにより、TypeScript の型検査、IDE のシンボルリネーム、多次元変数の添字参照(`${flow[i][j]}`)がそのまま機能します。
53
- 2. **ソルバーアダプター**: 共通のモデリング API から HiGHS・Z3・GLPK を利用でき、[独自アダプターも登録できます](https://github.com/ohtaman/washi/blob/main/docs/ja/solvers/custom-solver.md)。モデルの問題クラスを扱えるソルバーを選ぶ必要があり、対応機能はソルバーごとに異なります。
54
- 3. **ローカル実行と WebAssembly の配布**: ローカルソルバーのアダプターでは、別途 Python サービスや C/C++ のネイティブビルドを用意せずアプリケーション内で求解できるため、プロトタイプから Web ツールを公開する際のバックエンド構築のボトルネックを解消でき、ブラウザ内 LLM(WebGPU / WebLLM 等)とのクライアントサイド連携も容易です。ブラウザへの配布には生成された JS・Worker・WASM が必要です。オフライン利用には、これらをローカルに配置するかキャッシュしておく必要があります。Z3 には追加のブラウザ隔離設定があります。
55
- 4. **名前付き制約と矛盾原因の特定**: 充足可能性チェック(`m.check()`)により、矛盾した制約(`conflicts` / `unsatCore`)を調査して実行不能の原因を特定できます。組み込み HiGHS では**エラスティック修復集合**(実行可能性の回復のために緩和が必要な制約集合 `conflicts`)を検出し、Z3 では **SMT 充足不能コア**(相互に矛盾する制約部分集合 `unsatCore` / `conflicts`、最小性は保証されません)を抽出します。
56
- 5. **高度な分解法オーケストレーション**: 素朴な一体型 MIP では探索木が爆発するボトルネック構造(カッティングストック、配送計画/VRP、巡回セールスマン/TSP、施設配置計画など)を、ファーストクラスの分解法(`master.solveColumnGeneration`, `master.solveBenders`)で克服します。価格付け(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/ja/)**: モデリングガイド・ソルバー仕様・環境別の導入手順
40
+ - **[ショーケース](https://washi.ohtaman.dev/ja/showcase/) & [ブラウザデモ](https://washi.ohtaman.dev/demo/)**: ブラウザ上で動くデモアプリ集とプレイグラウンド
41
+ - **[サンプル集](https://washi.ohtaman.dev/ja/examples/)**: 課題別の実践レシピと実行可能なサンプルコード([`examples/`](examples/README.md))
42
+ - **[AIエージェント向けガイド](docs/ja/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 論理制約・Unsat Core 診断を使う場合
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
- 1次元辞書や2次元マトリクス変数を1行で宣言し、`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
- // 1次元辞書形式のバイナリ変数群
121
- const openCity = m.binary(["Tokyo", "Osaka", "Nagoya"]);
122
-
123
- // 2次元輸送量行列: [工場] x [店舗]
124
- const flow = m.continuous(["F1", "F2"], ["StoreA", "StoreB"], { lb: 0, ub: 1000 });
125
-
126
- // 2次元グリッド (例: 8x8 チェス盤)
127
- const board = m.binary(8, 8, { prefix: "queen" });
128
-
129
- // 条件付き Big-M 制約: 東京拠点が閉鎖 (openCity['Tokyo'] == 0) なら flow <= 0
130
- // (M を省略すると、変数の有限な上下限から安全な最小の 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`, "木材上限");
68
+ m.constraint(expr`2 * ${x} + ${y} <= 50`, "労働力上限");
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()` が単一 solve の弾性スラック緩和($\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: エンジニア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人 * $8000 = $64,000 > $50,000!)
256
- m.constraint(expr`${budget} <= 50000`, "strict_board_budget_cap");
76
+ ## ⚙️ 対応ソルバー
257
77
 
258
- // ルール 5: 最低 1 人雇用の労働基準(無関係なルール)
259
- m.constraint(expr`${engineers} >= 1`, "minimum_one_employee");
260
-
261
- // 1. 標準の HiGHS によるエラスティック修復診断
262
- const res = await m.check();
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`) |
263
84
 
264
- console.log(`ステータス: ${res.status}`); // "Unsat"
265
- console.log("修復対象制約(緩和が必要な制約):", res.conflicts);
266
- // HiGHS の出力: ["rush_required"]
267
- // (rush_required を緩和すれば実行可能となるため修復対象として特定されます)
268
-
269
- // 2. または Z3 による厳密な SMT 充足不能コア抽出(import "@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
+ プラグインを import した上で、`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) ソルバープラグインを利用する場合:
89
+ ## 🚀 基本的な使い方
280
90
 
281
- ```ts
282
- import { Model, expr, maximize } from "@ohtaman/washi";
283
- import "@ohtaman/washi/solvers/glpk";
91
+ ### 1. 総和・内積(`sum` / `dot`)と条件付き制約
284
92
 
285
- const m = new Model({ solver: "glpk" });
286
- const x = m.integer("x", { lb: 0 });
287
- const y = m.integer("y", { lb: 0 });
288
-
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
- ネストしたループを書くことなく、1次元・2次元の線形結合を1行で記述:
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 });
108
+
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");
317
112
 
318
- // 総輸送コストを1行で最小化:
319
- m.objective(minimize(dot(costs, ship)));
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
- `dist/browser` 一式(JS の分割ファイル・`highs.wasm`・Worker を含む)を HTTP 配信します。Import Maps は不要です。
140
+ 論理条件(`m.bool`, `implies`)を含むモデルの充足可能性を判定し、矛盾時の原因制約を特定します:
141
+ - **HiGHS(標準)**: 緩和すれば実行可能になる**修復集合**(`res.conflicts`)を特定します。
142
+ - **Z3**: 相互に矛盾している**充足不能コア**(`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"; // 厳密な 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` を公開します。CodePen の External Scripts にその URL を追加するか、次のように読み込みます。
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 から直接読み込む場合は、URL を `https://cdn.jsdelivr.net/npm/@ohtaman/washi@<version>/dist/browser/washi.min.js`(対応版リリースが公開された後にそのバージョンを指定)に指定できます。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 の URL を指定して読み込みます。
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 利用と Cross-Origin Isolation**:
406
- > Z3 の WebAssembly エンジンはマルチスレッド(`SharedArrayBuffer`)を必要とするため、`Cross-Origin-Opener-Policy: same-origin` および `Cross-Origin-Embedder-Policy: require-corp` ヘッダーによる Cross-Origin Isolation が必要です。静的ホスティング(`coi-serviceworker.js`)、イントラネット・オフライン配置、CSP(`worker-src blob:`)、カスタム WASM URL(`setHighsWasmUrl`)の詳細は [Cross-Origin Isolation 設定](docs/ja/getting-started/cross-origin.md) および [ランタイム環境とデプロイ構成](docs/ja/getting-started/runtimes.md) を参照してください。
407
-
408
- 完全なスタンドアロンサンプル(ESM、スクリプトタグ、CodePen)は [`examples/distribution/`](examples/distribution/README.md) に用意されています。
185
+ > **ブラウザでの Z3 利用**: Z3 の WebAssembly は `SharedArrayBuffer` を使用するため、Cross-Origin Isolation(`COOP: same-origin` / `COEP: require-corp`)が必要です。詳細は [Cross-Origin Isolation 設定](docs/ja/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
- - 詳細な開発手順、API コントラクト仕様(`Solver`, `SolveModelData`, `CheckModelData`, `SolverResult`)、およびテスト手法については [カスタムソルバー開発ガイド](docs/ja/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/ja/](https://ohtaman.github.io/washi/ja/)** およびリポジトリの [`docs/ja/`](docs/ja/)([英語版 `docs/`](docs/))で公開されています:
197
+ WaSHI は、数理最適化および自動推論分野の素晴らしいオープンソースソフトウェアの上に成り立っています:
423
198
 
424
- - **はじめに**: [クイックスタート](docs/ja/getting-started/index.md) · [AIエージェント向けクイックリファレンス](docs/ja/getting-started/ai-agents.md) · [ランタイム環境とデプロイ構成](docs/ja/getting-started/runtimes.md) · [Cross-Origin Isolation (Z3)](docs/ja/getting-started/cross-origin.md)
425
- - **モデリングガイド**: [決定変数 (`Var`, `BoolVar`)](docs/ja/guide/variables.md) · [数式と集計 (`expr`, `sum`, `dot`)](docs/ja/guide/expressions.md) · [制約と論理条件 (`indicator`, SMT)](docs/ja/guide/constraints.md) · [目的関数と求解 (`solve`, `validateSolution`)](docs/ja/guide/objectives.md) · [充足可能性と Unsat Core (`check`)](docs/ja/guide/unsat-core.md) · [分解法 (`solveColumnGeneration`, `solveBenders`)](docs/ja/guide/decomposition.md)
426
- - **ソルバー**: [ソルバー概要](docs/ja/solvers/index.md) · [HiGHS](docs/ja/solvers/highs.md) · [Z3](docs/ja/solvers/z3.md) · [GLPK](docs/ja/solvers/glpk.md) · [カスタムソルバー](docs/ja/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/ja/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) | 2次元マトリクス変数 (`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
- | **実践応用** | [ECカートのクーポン最適適用](https://github.com/ohtaman/washi/blob/main/examples/node/12-ecommerce-coupon-optimizer.ts) | 条件付き購入金額閾値 (`indicator`)、併用不可ルール、追加購入提案 | HiGHS |
441
- | **分解法 (OR)** | [配送計画 (CVRP)](https://github.com/ohtaman/washi/blob/main/examples/node/13-vehicle-routing-column-generation.ts) | 列生成法 (Dantzig-Wolfe): 双対変数を用いた実行可能車両ルートの動的プライシング | HiGHS |
442
- | **分解法 (OR)** | [巡回セールスマン (TSP)](https://github.com/ohtaman/washi/blob/main/examples/node/14-traveling-salesperson-benders.ts) | ベンダーズ分解 (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 は Cross-Origin Isolation が必要です。詳細は上記のブラウザ要件に記載しています。
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/` モジュールを import しています。公開パッケージを使うアプリでは、`@ohtaman/washi` と必要なソルバープラグインから import してください。
468
-
469
- ---
470
-
471
- ## 🧪 テスト & 再現可能なベンチマーク
472
-
473
- リポジトリのユニット・統合テストを実行し、配布物をビルドできます:
474
-
475
- ```bash
476
- # すべてのユニット・統合テストを実行
477
- npm test
478
-
479
- # プロダクション用バンドルと型定義を生成
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 マージ後、オンデマンド取得(scripts/ensure-highs-wasm.mjs)のハッシュと一致するよう
509
- # 対応する highs-<version> GitHub Release タグのアセットを上書きアップロード:
510
- gh release upload highs-v1.15.1 public/highs.wasm src/modeler/solvers/highs/runtime.js --clobber
511
- ```
512
- (GitHub Actions の **Build HiGHS WebAssembly** ワークフロー `.github/workflows/build-wasm.yml` を `create_release: true` で手動実行することも可能です。その場合は生成された `highs-wasm-assets` アーティファクト(`public/highs.wasm`、`src/modeler/solvers/highs/runtime.js`、`highs.config.json`)を取得してリポジトリへコミットし、Release アセットと SHA-256 ハッシュを同期してください。)
513
-
514
- 2. **`@ohtaman/washi` の npm パッケージリリース**:
515
- - `main` ブランチへのマージにより、ドキュメントと Web デモは GitHub Pages(`.github/workflows/deploy-demo.yml`)へ自動デプロイされますが、npm への公開は自動では行われません。
516
- - npm に新バージョンを公開する場合は、`package.json` の `"version"` を更新して `main` にマージした上で、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 により開発された SMT ソルバーであり、オプションの論理充足判定および `unsatCore` 矛盾診断プラグインを支えています。
201
+ - **[GLPK](https://www.gnu.org/software/glpk/) & [`glpk.js`](https://github.com/jvail/glpk.js)** — オプションの 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) を参照してください。