@ohtaman/washi 0.5.0 → 0.6.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.
- package/README.ja.md +55 -20
- package/README.md +55 -20
- package/README.zh-CN.md +55 -20
- package/THIRD_PARTY_LICENSES.md +3 -4
- package/dist/browser/_washi-node-only-BvRk9kiK.js +0 -0
- package/dist/browser/browser-runtime-TLCY0hkc.js +1793 -0
- package/dist/browser/highs-worker.js +1 -1
- package/dist/browser/highs.wasm +0 -0
- package/dist/browser/highs.wasm.LICENSE +1 -2
- package/dist/browser/loader-DewlSho8.js +643 -0
- package/dist/browser/solvers/glpk.js +1 -1
- package/dist/browser/solvers/glpk.min.js +1 -1
- package/dist/browser/solvers/z3.js +7 -1
- package/dist/browser/solvers/z3.min.js +1 -1
- package/dist/browser/washi.js +1096 -444
- package/dist/browser/washi.min.js +3 -4
- package/dist/lib/_washi-node-only-BvRk9kiK.js +0 -0
- package/dist/lib/highs-browser-runtime.js +2120 -4124
- package/dist/lib/highs-node-runtime.js +24 -1
- package/dist/lib/highs-runtime.js +2 -0
- package/dist/lib/highs-worker.js +1 -1
- package/dist/lib/highs.wasm +0 -0
- package/dist/lib/highs.wasm.LICENSE +1 -2
- package/dist/lib/loader-BZUQNvh4.js +649 -0
- package/dist/lib/{registry-BEfvpZW3.js → registry-C20sxTwm.js} +54 -41
- package/dist/lib/solvers/glpk.js +2 -2
- package/dist/lib/solvers/z3.js +1 -1
- package/dist/lib/washi.js +973 -305
- package/dist/types/decomposition/benders.d.ts +32 -0
- package/dist/types/decomposition/benders.d.ts.map +1 -0
- package/dist/types/decomposition/column-generation.d.ts +34 -0
- package/dist/types/decomposition/column-generation.d.ts.map +1 -0
- package/dist/types/decomposition/index.d.ts +4 -0
- package/dist/types/decomposition/index.d.ts.map +1 -0
- package/dist/types/decomposition/types.d.ts +230 -0
- package/dist/types/decomposition/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modeler/boolean-expr.d.ts.map +1 -1
- package/dist/types/modeler/constraint.d.ts +11 -0
- package/dist/types/modeler/constraint.d.ts.map +1 -1
- package/dist/types/modeler/expression.d.ts +10 -0
- package/dist/types/modeler/expression.d.ts.map +1 -1
- package/dist/types/modeler/index.d.ts +2 -1
- package/dist/types/modeler/index.d.ts.map +1 -1
- package/dist/types/modeler/linearizer.d.ts +15 -0
- package/dist/types/modeler/linearizer.d.ts.map +1 -0
- package/dist/types/modeler/lp-writer.d.ts +3 -1
- package/dist/types/modeler/lp-writer.d.ts.map +1 -1
- package/dist/types/modeler/model.d.ts +147 -2
- package/dist/types/modeler/model.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/browser-runtime.d.ts +2 -1
- package/dist/types/modeler/solvers/highs/browser-runtime.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/driver.d.ts +232 -0
- package/dist/types/modeler/solvers/highs/driver.d.ts.map +1 -0
- package/dist/types/modeler/solvers/highs/index.d.ts +1 -0
- package/dist/types/modeler/solvers/highs/index.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/loader.d.ts +4 -4
- package/dist/types/modeler/solvers/highs/loader.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/node-runtime.d.ts +2 -1
- package/dist/types/modeler/solvers/highs/node-runtime.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/solver.d.ts +1 -1
- package/dist/types/modeler/solvers/highs/solver.d.ts.map +1 -1
- package/dist/types/modeler/solvers/types.d.ts +2 -0
- package/dist/types/modeler/solvers/types.d.ts.map +1 -1
- package/dist/types/modeler/types.d.ts +27 -0
- package/dist/types/modeler/types.d.ts.map +1 -1
- package/docs/examples/index.md +4 -0
- package/docs/examples/traveling-salesperson.md +173 -0
- package/docs/examples/vehicle-routing.md +206 -0
- package/docs/getting-started/ai-agents.md +8 -4
- package/docs/guide/constraints.md +1 -1
- package/docs/guide/decomposition.md +399 -0
- package/docs/guide/unsat-core.md +10 -3
- package/docs/ja/getting-started/ai-agents.md +8 -4
- package/docs/solvers/custom-solver.md +1 -1
- package/docs/solvers/highs.md +25 -3
- package/docs/solvers/index.md +3 -3
- package/docs/zh/getting-started/ai-agents.md +8 -4
- package/llms-full.txt +831 -15
- package/llms.txt +9 -5
- package/package.json +17 -14
- package/skills/washi/SKILL.md +8 -8
- package/dist/browser/browser-runtime-D13gHOT5.js +0 -4189
- package/dist/browser/loader-CtaDHef_.js +0 -273
- package/dist/lib/loader-DmNC_UNk.js +0 -279
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
|
|
5
|
+
<img alt="WaSHI - 数理最適化と制約プログラミングのための代数モデラー (TypeScript / JavaScript)" src="./assets/washi-header-light.png" width="420" />
|
|
6
6
|
</picture>
|
|
7
|
-
<p><strong
|
|
7
|
+
<p><strong>数理最適化と制約プログラミングのための代数モデラー</strong></p>
|
|
8
8
|
<p>
|
|
9
9
|
<em>線形計画 (LP) • 混合整数計画 (MIP) • 凸二次計画 (QP) • SMT論理制約 & 矛盾診断</em>
|
|
10
10
|
</p>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
**WaSHI**(WebAssembly-backed, Solver-independent, High-level modeling Interface)は、Python の **PuLP** や Julia の **JuMP**
|
|
27
|
+
**WaSHI**(WebAssembly-backed, Solver-independent, High-level modeling Interface)は、Python の **PuLP** や Julia の **JuMP** に着想を得た、数理最適化と制約プログラミングのための TypeScript / JavaScript 向け代数モデラーです。アプリケーションのコードで変数・目的関数・数値制約や論理制約を記述できます。WaSHI はモデルの構築、ソルバー向けの変換、変数への結果の反映を担当し、最適化や充足可能性の判定は **HiGHS**・**Z3**・**GLPK** が行います。
|
|
28
28
|
|
|
29
29
|
HiGHS が標準ソルバーで、Z3 と GLPK は任意で追加するプラグインです。Node.js 用とブラウザ用の配布物に WebAssembly アセットを含みます。配信に必要な設定は[ブラウザでの利用方法](#-ブラウザ--web-worker-での利用方法)を参照してください。
|
|
30
30
|
|
|
@@ -52,7 +52,8 @@ console.log(`生産量: x=${x.value}, y=${y.value} (最大利益: $${m.objective
|
|
|
52
52
|
1. **代数的なモデル記述**: ドメイン変数メソッド(`m.binary`, `m.integer`, `m.continuous`)、タグ付きテンプレート(`expr`)、ベクトル集計関数(`dot`, `sum`)、およびファーストクラスの制約(`m.constraint`)によりモデルを記述します。JavaScript には演算子オーバーロードがないため、`` expr`...` `` は SQL のパラメータバインディングと同様に、中置記法の演算子(`+`, `-`, `*`, `^2`, `<=`, `>=`, `==`)を構文解析しつつ `${...}` に渡された値を型付きの `Var` や式のオブジェクト参照として直接バインドします。これにより、TypeScript の型検査、IDE のシンボルリネーム、多次元変数の添字参照(`${flow[i][j]}`)がそのまま機能します。
|
|
53
53
|
2. **ソルバーアダプター**: 共通のモデリング API から HiGHS・Z3・GLPK を利用でき、[独自アダプターも登録できます](https://github.com/ohtaman/washi/blob/main/docs/ja/solvers/custom-solver.md)。モデルの問題クラスを扱えるソルバーを選ぶ必要があり、対応機能はソルバーごとに異なります。
|
|
54
54
|
3. **ローカル実行と WebAssembly の配布**: ローカルソルバーのアダプターでは、別途 Python サービスや C/C++ のネイティブビルドを用意せずアプリケーション内で求解できるため、プロトタイプから Web ツールを公開する際のバックエンド構築のボトルネックを解消でき、ブラウザ内 LLM(WebGPU / WebLLM 等)とのクライアントサイド連携も容易です。ブラウザへの配布には生成された JS・Worker・WASM が必要です。オフライン利用には、これらをローカルに配置するかキャッシュしておく必要があります。Z3 には追加のブラウザ隔離設定があります。
|
|
55
|
-
4.
|
|
55
|
+
4. **名前付き制約と矛盾原因の特定**: 充足可能性チェック(`m.check()`)により、矛盾した制約(`conflicts` / `unsatCore`)を調査して実行不能の原因を特定できます。組み込み HiGHS では**エラスティック修復集合**(実行可能性の回復のために緩和が必要な制約集合 `conflicts`)を検出し、Z3 では **SMT 充足不能コア**(相互に矛盾する制約部分集合 `unsatCore` / `conflicts`、最小性は保証されません)を抽出します。
|
|
56
|
+
5. **高度な分解法オーケストレーション**: 素朴な一体型 MIP では探索木が爆発するボトルネック構造(カッティングストック、配送計画/VRP、巡回セールスマン/TSP、施設配置計画など)を、ファーストクラスの分解法(`master.solveColumnGeneration`, `master.solveBenders`)で克服します。価格付け(Pricing)や連結制約(`sub.link(...)`)を活用したクリーンなコールバック設計により、双対価格付け・カット生成・整数解の復元をきれいに調整します。
|
|
56
57
|
|
|
57
58
|
モデルの構築と変換は WaSHI が担当します。扱える問題クラス、数値計算の挙動、求解時間は、選択したソルバー・設定・問題に依存します。モデル構築のオーバーヘッドとソルバーの実行時間は分けて計測する必要があり、特定のモデルでの結果は一般的な性能保証ではありません。
|
|
58
59
|
|
|
@@ -62,9 +63,9 @@ console.log(`生産量: x=${x.value}, y=${y.value} (最大利益: $${m.objective
|
|
|
62
63
|
|
|
63
64
|
| アダプター | エンジンのライセンス | 対応する問題クラス | エンジンの役割 | 提供形態 |
|
|
64
65
|
| :--- | :--- | :--- | :--- | :--- |
|
|
65
|
-
| **HiGHS** | **MIT** | **LP, MIP, 凸QP** | 数値最適化 | 標準ソルバー |
|
|
66
|
-
| **Z3** | **MIT** | **SMT, SAT, 命題論理, MIP** | 充足可能性の判定、Unsat Core、最適化 | オプションプラグイン (`@ohtaman/washi/solvers/z3`) |
|
|
67
|
-
| **GLPK** | **GPL-3.0** | **LP, MIP** | 線形・混合整数最適化 | オプションプラグイン (`@ohtaman/washi/solvers/glpk`) |
|
|
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`) |
|
|
68
69
|
| **Mock** | **MIT** | — | 統合テスト用の模擬応答 | 標準搭載。モデルの求解は行わない |
|
|
69
70
|
|
|
70
71
|
---
|
|
@@ -92,9 +93,13 @@ npm install z3-solver # SMT・矛盾診断を利用する場合
|
|
|
92
93
|
npm install glpk.js # GLPK ソルバーを利用する場合 (GPL-3.0)
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
*(任意)* AI コーディングエージェント(Claude Code, Antigravity, Cursor, Codex
|
|
96
|
+
*(任意)* AI コーディングエージェント(Claude Code, Antigravity, Cursor, Codex 等)向けに、`skills` CLI またはパッケージ同梱の [`skills/washi/SKILL.md`](skills/washi/SKILL.md) を導入できます:
|
|
96
97
|
|
|
97
98
|
```bash
|
|
99
|
+
# skills CLI (skills.sh / vercel-labs/skills) 経由で導入
|
|
100
|
+
npx skills add ohtaman/washi
|
|
101
|
+
|
|
102
|
+
# またはパッケージ同梱のスキルを手動で配置
|
|
98
103
|
mkdir -p .agents/skills/washi
|
|
99
104
|
cp node_modules/@ohtaman/washi/skills/washi/SKILL.md .agents/skills/washi/SKILL.md
|
|
100
105
|
```
|
|
@@ -224,15 +229,16 @@ console.log(`サイレン作動? ${m.values.get("siren")}`); // true
|
|
|
224
229
|
|
|
225
230
|
---
|
|
226
231
|
|
|
227
|
-
### 4.
|
|
232
|
+
### 4. 矛盾診断(`conflicts` / `unsatCore`)
|
|
228
233
|
|
|
229
|
-
|
|
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`)を返します。
|
|
230
237
|
|
|
231
238
|
```ts
|
|
232
239
|
import { Model, expr } from "@ohtaman/washi";
|
|
233
|
-
import "@ohtaman/washi/solvers/z3";
|
|
234
240
|
|
|
235
|
-
const m = new Model(
|
|
241
|
+
const m = new Model("ConflictDiagnosis");
|
|
236
242
|
const engineers = m.integer("engineers", { lb: 0, ub: 20 });
|
|
237
243
|
const budget = m.continuous("budget", { lb: 0, ub: 100000 });
|
|
238
244
|
const rushDelivery = m.bool("rushDelivery");
|
|
@@ -252,12 +258,18 @@ m.constraint(expr`${budget} <= 50000`, "strict_board_budget_cap");
|
|
|
252
258
|
// ルール 5: 最低 1 人雇用の労働基準(無関係なルール)
|
|
253
259
|
m.constraint(expr`${engineers} >= 1`, "minimum_one_employee");
|
|
254
260
|
|
|
255
|
-
|
|
261
|
+
// 1. 標準の HiGHS によるエラスティック修復診断
|
|
262
|
+
const res = await m.check();
|
|
256
263
|
|
|
257
264
|
console.log(`ステータス: ${res.status}`); // "Unsat"
|
|
258
|
-
console.log("
|
|
259
|
-
//
|
|
260
|
-
//
|
|
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"]
|
|
261
273
|
```
|
|
262
274
|
|
|
263
275
|
---
|
|
@@ -410,7 +422,7 @@ WaSHI は疎結合なプラグイン方式のソルバーアーキテクチャ
|
|
|
410
422
|
完全なドキュメントは **[ohtaman.github.io/washi/ja/](https://ohtaman.github.io/washi/ja/)** およびリポジトリの [`docs/ja/`](docs/ja/)([英語版 `docs/`](docs/))で公開されています:
|
|
411
423
|
|
|
412
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)
|
|
413
|
-
- **モデリングガイド**: [決定変数 (`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)
|
|
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)
|
|
414
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)
|
|
415
427
|
|
|
416
428
|
---
|
|
@@ -426,6 +438,8 @@ WaSHI は疎結合なプラグイン方式のソルバーアーキテクチャ
|
|
|
426
438
|
| **基本モデル** | [栄養問題と感度分析](https://github.com/ohtaman/washi/blob/main/examples/node/10-diet-sensitivity.ts) | 潜在価格 (`constr.dual`)、余剰 (`constr.slack`)、被約費用 (`var.reducedCost`) | HiGHS |
|
|
427
439
|
| **実践応用** | [スタッフのシフト作成](https://github.com/ohtaman/washi/blob/main/examples/node/11-shift-scheduling.ts) | 週間シフト最適化と、土曜日の希望休が衝突した際の原因特定 | HiGHS + Z3 |
|
|
428
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 |
|
|
429
443
|
| **実践応用** | [ポートフォリオ配分](https://github.com/ohtaman/washi/blob/main/examples/node/03-portfolio-qp.ts) | 凸二次目的関数 (`QuadExpr`) と配分の制約 | HiGHS |
|
|
430
444
|
| **論理 / SMT** | [業務ルールの検証](https://github.com/ohtaman/washi/blob/main/examples/node/04-smt-security-rules.ts) | 数値・論理制約 (`bool`, `implies`) の充足可能性の確認 | Z3 |
|
|
431
445
|
| **論理 / SMT** | [矛盾する制約の診断](https://github.com/ohtaman/washi/blob/main/examples/node/05-unsat-core-diagnosis.ts) | 名前付き制約と Unsat Core (`unsatCore`) | Z3 |
|
|
@@ -443,6 +457,8 @@ npx tsx examples/node/09-transportation-problem.ts
|
|
|
443
457
|
npx tsx examples/node/10-diet-sensitivity.ts
|
|
444
458
|
npx tsx examples/node/11-shift-scheduling.ts
|
|
445
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
|
|
446
462
|
|
|
447
463
|
# ローカルのブラウザデモ: http://localhost:5173/demo/
|
|
448
464
|
npm run dev
|
|
@@ -482,11 +498,30 @@ node scripts/run-benchmarks.mjs --browser
|
|
|
482
498
|
- **明示的な計測境界**: コールド初期化(`coldRuntimeInitMs`, `coldFirstSolveMs`)と再利用ランタイムでの反復計測(`modelBuildMs`, `validationMs`, LP文字列アダプタ向けの `lpSerializationMs` または構造化アダプタ向けの `symbolMapMs`, `MockSolver` による `resultMappingMs`, `adapterSolveMs`, `endToEndSolveMs`)を分離して直接計測します(無関係なフェーズ時間を差し引いて「ネイティブソルバー時間」とみなすことはしません)。
|
|
483
499
|
- **実行環境の区別**: Node.js のインプロセス WASM(`usesBrowserWorker: false`)とブラウザ Web Worker 実行(`usesBrowserWorker: true`、Worker ライフサイクルや `postMessage` 転送を含む)は異なる実行環境として区別してレポートされます。
|
|
484
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 へ公開されます。
|
|
517
|
+
|
|
485
518
|
---
|
|
486
519
|
|
|
487
520
|
## 📄 ライセンス
|
|
488
521
|
|
|
489
522
|
- **`@ohtaman/washi`**: [MIT ライセンス](./LICENSE)
|
|
490
|
-
- **HiGHS
|
|
491
|
-
- **Z3
|
|
492
|
-
- **GLPK
|
|
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) をご覧ください。
|
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
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 - Algebraic Modeler for
|
|
5
|
+
<img alt="WaSHI - Algebraic Modeler for Mathematical Optimization & Constraint Programming" src="./assets/washi-header-light.png" width="420" />
|
|
6
6
|
</picture>
|
|
7
|
-
<p><strong>Algebraic
|
|
7
|
+
<p><strong>Algebraic Modeler for Mathematical Optimization & Constraint Programming</strong></p>
|
|
8
8
|
<p>
|
|
9
|
-
<em>Linear Programming (LP) • Mixed-Integer Programming (MIP) • Quadratic Programming (QP) • SMT & Conflict Diagnosis</em>
|
|
9
|
+
<em>Linear Programming (LP) • Mixed-Integer Programming (MIP) • Convex Quadratic Programming (QP) • SMT & Conflict Diagnosis</em>
|
|
10
10
|
</p>
|
|
11
11
|
<p>
|
|
12
12
|
<a href="./README.md">English</a> •
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
**WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) is an algebraic modeler for TypeScript and JavaScript, inspired by Python's **PuLP** and Julia's **JuMP**. Define variables, objectives, and arithmetic or logical constraints in application code. WaSHI constructs the model, translates it for a solver adapter, and maps results back to your variables. **HiGHS**, **Z3**, and **GLPK** perform the optimization or satisfiability checks.
|
|
27
|
+
**WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) is an algebraic modeler for mathematical optimization and constraint programming in TypeScript and JavaScript, inspired by Python's **PuLP** and Julia's **JuMP**. Define variables, objectives, and arithmetic or logical constraints in application code. WaSHI constructs the model, translates it for a solver adapter, and maps results back to your variables. **HiGHS**, **Z3**, and **GLPK** perform the optimization or satisfiability checks.
|
|
28
28
|
|
|
29
29
|
HiGHS is the default solver; Z3 and GLPK are optional plugins. The package provides Node.js and browser distributions, including WebAssembly assets. See the [browser integration guide](#-browser--web-worker-usage) for deployment requirements.
|
|
30
30
|
|
|
@@ -52,7 +52,8 @@ console.log(`Produce: x=${x.value}, y=${y.value} (Profit: $${m.objectiveValue})`
|
|
|
52
52
|
1. **Algebraic model construction**: Formulate optimization models using domain-specific variable constructors (`m.binary`, `m.integer`, `m.continuous`), unified tagged template literals (`expr`), vector aggregations (`dot`, `sum`), and first-class constraints (`m.constraint`). Because JavaScript lacks operator overloading, `` expr`...` `` parses infix math (`+`, `-`, `*`, `^2`, `<=`, `>=`, `==`) while binding interpolated `${...}` values directly as typed `Var` or expression references—similar to parameterized SQL templates—preserving static type checking, IDE refactoring, and indexed variable lookups (`${flow[i][j]}`).
|
|
53
53
|
2. **Solver adapters**: Use a common modeling API with HiGHS, Z3, or GLPK, or [register your own adapter](https://github.com/ohtaman/washi/blob/main/docs/solvers/custom-solver.md). Choose an engine that supports the model's problem class; the adapters do not make every solver support every feature.
|
|
54
54
|
3. **Local execution and WebAssembly distribution**: With the local solver adapters, solving runs in the application without a separate Python service or native C/C++ build—removing backend provisioning as a bottleneck when shipping interactive tools or combining mathematical optimization with in-browser LLMs (e.g., WebGPU / WebLLM) on the client. Browser deployments must include the generated JS, Worker, and WASM assets. Offline use also requires those resources to be available locally or cached. Z3 has additional browser isolation requirements.
|
|
55
|
-
4. **Named constraints and
|
|
55
|
+
4. **Named constraints and conflict diagnosis**: Explicitly check satisfiability (`m.check()`) and inspect conflicting constraints (`conflicts` / `unsatCore`) to investigate infeasibilities: built-in HiGHS isolates an **elastic repair set** (`conflicts`, constraints requiring relaxation to restore feasibility), while Z3 extracts an **unsatisfiable core** (`unsatCore` / `conflicts`, a mutually contradictory constraint subset; minimality is not guaranteed).
|
|
56
|
+
5. **Advanced decomposition methods**: Overcome combinatorial bottlenecks in monolithic MIP formulations (cutting stock, vehicle routing/VRP, traveling salesperson/TSP, and two-stage facility planning) using first-class decomposition orchestrators (`master.solveColumnGeneration`, `master.solveBenders`). WaSHI coordinates dual shadow prices, pricing subproblems, and Benders cut generation via clean callback orchestrators and linking constraints (`sub.link(...)`).
|
|
56
57
|
|
|
57
58
|
Model construction and translation are WaSHI's responsibility. Supported problem classes, numerical behavior, and solve time depend on the selected solver, its settings, and the problem. Modeling overhead and solver execution time should be measured separately; a result for one model is not a general performance guarantee.
|
|
58
59
|
|
|
@@ -62,9 +63,9 @@ Model construction and translation are WaSHI's responsibility. Supported problem
|
|
|
62
63
|
|
|
63
64
|
| Adapter | Engine license | Supported problem classes | Engine role | Integration |
|
|
64
65
|
| :--- | :--- | :--- | :--- | :--- |
|
|
65
|
-
| **HiGHS** | **MIT** | **LP, MIP, convex QP** | Numerical optimization | Built-in default |
|
|
66
|
-
| **Z3** | **MIT** | **SMT, SAT, logic, MIP** | Satisfiability checks, unsatisfiable cores, optimization | Optional plugin (`@ohtaman/washi/solvers/z3`) |
|
|
67
|
-
| **GLPK** | **GPL-3.0** | **LP, MIP** | Linear and mixed-integer optimization | Optional plugin (`@ohtaman/washi/solvers/glpk`) |
|
|
66
|
+
| **[HiGHS](https://github.com/ERGO-Code/HiGHS)** | **MIT** | **LP, MIP, convex QP** | Numerical optimization | Built-in default |
|
|
67
|
+
| **[Z3](https://github.com/Z3Prover/z3)** (via [`z3-solver`](https://www.npmjs.com/package/z3-solver)) | **MIT** | **SMT, SAT, logic, MIP** | Satisfiability checks, unsatisfiable cores, optimization | Optional plugin (`@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** | Linear and mixed-integer optimization | Optional plugin (`@ohtaman/washi/solvers/glpk`) |
|
|
68
69
|
| **Mock** | **MIT** | — | Simulated solver responses for integration tests | Built-in; does not solve the model |
|
|
69
70
|
|
|
70
71
|
---
|
|
@@ -92,9 +93,13 @@ npm install z3-solver # For SMT and unsat core diagnosis
|
|
|
92
93
|
npm install glpk.js # For GLPK solver (GPL-3.0)
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
*(Optional)* For AI coding agents (Claude Code, Antigravity, Cursor, Codex, etc.),
|
|
96
|
+
*(Optional)* For AI coding agents (Claude Code, Antigravity, Cursor, Codex, etc.), install the portable [`skills/washi/SKILL.md`](skills/washi/SKILL.md) workflow directly via the `skills` CLI or copy it from the installed package:
|
|
96
97
|
|
|
97
98
|
```bash
|
|
99
|
+
# Install via the open skills CLI (skills.sh / vercel-labs/skills)
|
|
100
|
+
npx skills add ohtaman/washi
|
|
101
|
+
|
|
102
|
+
# Or manually copy the packaged skill into your project's agent directory
|
|
98
103
|
mkdir -p .agents/skills/washi
|
|
99
104
|
cp node_modules/@ohtaman/washi/skills/washi/SKILL.md .agents/skills/washi/SKILL.md
|
|
100
105
|
```
|
|
@@ -226,13 +231,14 @@ console.log(`Siren active? ${m.values.get("siren")}`); // true
|
|
|
226
231
|
|
|
227
232
|
### 4. Conflict Diagnosis (`conflicts` / `unsatCore`)
|
|
228
233
|
|
|
229
|
-
When business rules or constraints contradict each other,
|
|
234
|
+
When business rules or constraints contradict each other, diagnose infeasibilities to pinpoint where to intervene:
|
|
235
|
+
- **Built-in HiGHS & GLPK**: `await m.check()` uses a single-solve elastic slack formulation ($\min \sum s_i$) to isolate `res.conflicts`—the **repair set** of constraints whose relaxation restores feasibility, without requiring extra dependencies.
|
|
236
|
+
- **Z3**: `await m.check({ solver: "z3" })` provides exact SMT **unsatisfiable-core** extraction (`res.unsatCore` and `res.conflicts`), returning a mutually contradictory constraint subset.
|
|
230
237
|
|
|
231
238
|
```ts
|
|
232
239
|
import { Model, expr } from "@ohtaman/washi";
|
|
233
|
-
import "@ohtaman/washi/solvers/z3";
|
|
234
240
|
|
|
235
|
-
const m = new Model(
|
|
241
|
+
const m = new Model("ConflictDiagnosis");
|
|
236
242
|
const engineers = m.integer("engineers", { lb: 0, ub: 20 });
|
|
237
243
|
const budget = m.continuous("budget", { lb: 0, ub: 100000 });
|
|
238
244
|
const rushDelivery = m.bool("rushDelivery");
|
|
@@ -252,12 +258,18 @@ m.constraint(expr`${budget} <= 50000`, "strict_board_budget_cap");
|
|
|
252
258
|
// Rule 5: Innocent bystander rule
|
|
253
259
|
m.constraint(expr`${engineers} >= 1`, "minimum_one_employee");
|
|
254
260
|
|
|
255
|
-
|
|
261
|
+
// 1. Elastic repair diagnosis with default HiGHS
|
|
262
|
+
const res = await m.check();
|
|
256
263
|
|
|
257
264
|
console.log(`Status: ${res.status}`); // "Unsat"
|
|
258
|
-
console.log("
|
|
259
|
-
// Output: ["
|
|
260
|
-
//
|
|
265
|
+
console.log("Repair set (relaxed constraints):", res.conflicts);
|
|
266
|
+
// Output with HiGHS: ["rush_required"]
|
|
267
|
+
// (Relaxing rush_required restores feasibility; innocent rules like minimum_one_employee are untouched)
|
|
268
|
+
|
|
269
|
+
// 2. Or exact SMT unsatisfiable core with Z3 (import "@ohtaman/washi/solvers/z3")
|
|
270
|
+
// const z3Res = await m.check({ solver: "z3" });
|
|
271
|
+
// console.log("Contradictory core:", z3Res.unsatCore);
|
|
272
|
+
// Output with Z3: ["budget_limit", "rush_required", "rush_staffing_rule", "strict_board_budget_cap"]
|
|
261
273
|
```
|
|
262
274
|
|
|
263
275
|
---
|
|
@@ -410,7 +422,7 @@ WaSHI features a decoupled, pluggable solver architecture. You can easily build
|
|
|
410
422
|
Full documentation is available at **[ohtaman.github.io/washi](https://ohtaman.github.io/washi/)** and in the repository's [`docs/`](docs/) directory:
|
|
411
423
|
|
|
412
424
|
- **Getting Started**: [Quick Start](docs/getting-started/index.md) · [AI Agent Quick-Reference](docs/getting-started/ai-agents.md) · [Runtime Environments](docs/getting-started/runtimes.md) · [Cross-Origin Isolation (Z3)](docs/getting-started/cross-origin.md)
|
|
413
|
-
- **Modeling Guide**: [Variables (`Var`, `BoolVar`)](docs/guide/variables.md) · [Expressions (`expr`, `sum`, `dot`)](docs/guide/expressions.md) · [Constraints & Logic (`indicator`, SMT)](docs/guide/constraints.md) · [Objectives & Solving (`solve`, `validateSolution`)](docs/guide/objectives.md) · [Feasibility & Unsat Core (`check`)](docs/guide/unsat-core.md)
|
|
425
|
+
- **Modeling Guide**: [Variables (`Var`, `BoolVar`)](docs/guide/variables.md) · [Expressions (`expr`, `sum`, `dot`)](docs/guide/expressions.md) · [Constraints & Logic (`indicator`, SMT)](docs/guide/constraints.md) · [Objectives & Solving (`solve`, `validateSolution`)](docs/guide/objectives.md) · [Feasibility & Unsat Core (`check`)](docs/guide/unsat-core.md) · [Decomposition (`solveColumnGeneration`, `solveBenders`)](docs/guide/decomposition.md)
|
|
414
426
|
- **Solvers**: [Solver Overview](docs/solvers/index.md) · [HiGHS](docs/solvers/highs.md) · [Z3](docs/solvers/z3.md) · [GLPK](docs/solvers/glpk.md) · [Custom Solvers](docs/solvers/custom-solver.md)
|
|
415
427
|
|
|
416
428
|
---
|
|
@@ -426,6 +438,8 @@ Start with the [example gallery](https://github.com/ohtaman/washi/blob/main/exam
|
|
|
426
438
|
| **Fundamentals** | [Diet & sensitivity analysis](https://github.com/ohtaman/washi/blob/main/examples/node/10-diet-sensitivity.ts) | Shadow prices (`constr.dual`), surpluses (`constr.slack`), and reduced costs (`var.reducedCost`) | HiGHS |
|
|
427
439
|
| **Practical** | [Staff shift scheduling](https://github.com/ohtaman/washi/blob/main/examples/node/11-shift-scheduling.ts) | Weekly roster optimization + diagnosing conflicting Saturday vacation requests | HiGHS + Z3 |
|
|
428
440
|
| **Practical** | [E-commerce coupon optimizer](https://github.com/ohtaman/washi/blob/main/examples/node/12-ecommerce-coupon-optimizer.ts) | Conditional spend thresholds (`indicator`), coupon exclusivity, and add-on recommendations | HiGHS |
|
|
441
|
+
| **Decomposition** | [Vehicle routing (CVRP)](https://github.com/ohtaman/washi/blob/main/examples/node/13-vehicle-routing-column-generation.ts) | Column Generation (Dantzig-Wolfe): pricing feasible vehicle routes from dual shadow prices | HiGHS |
|
|
442
|
+
| **Decomposition** | [Traveling salesperson (TSP)](https://github.com/ohtaman/washi/blob/main/examples/node/14-traveling-salesperson-benders.ts) | Benders Decomposition (DFJ): lazy subtour elimination constraints via feasibility cuts | HiGHS |
|
|
429
443
|
| **Practical** | [Portfolio allocation](https://github.com/ohtaman/washi/blob/main/examples/node/03-portfolio-qp.ts) | A convex quadratic objective (`QuadExpr`) with allocation constraints | HiGHS |
|
|
430
444
|
| **Logic / SMT** | [Business rule checks](https://github.com/ohtaman/washi/blob/main/examples/node/04-smt-security-rules.ts) | Arithmetic and Boolean constraints (`bool`, `implies`) with satisfiability checking | Z3 |
|
|
431
445
|
| **Logic / SMT** | [Conflict diagnosis](https://github.com/ohtaman/washi/blob/main/examples/node/05-unsat-core-diagnosis.ts) | Named constraints and an unsatisfiable core (`unsatCore`) | Z3 |
|
|
@@ -443,6 +457,8 @@ npx tsx examples/node/09-transportation-problem.ts
|
|
|
443
457
|
npx tsx examples/node/10-diet-sensitivity.ts
|
|
444
458
|
npx tsx examples/node/11-shift-scheduling.ts
|
|
445
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
|
|
446
462
|
|
|
447
463
|
# Local browser demo: http://localhost:5173/demo/
|
|
448
464
|
npm run dev
|
|
@@ -482,11 +498,30 @@ node scripts/run-benchmarks.mjs --browser
|
|
|
482
498
|
- **Explicit phase boundaries**: Reports cold runtime initialization (`coldRuntimeInitMs`, `coldFirstSolveMs`) separately from repeated warm-runtime measurements (`modelBuildMs`, `validationMs`, `lpSerializationMs` for LP-string adapters or `symbolMapMs` for structured adapters, `resultMappingMs` via `MockSolver`, `adapterSolveMs`, and `endToEndSolveMs`). Timings are measured directly per phase and are never subtracted to estimate "native solver time".
|
|
483
499
|
- **Distinct execution environments**: Node.js in-process WASM (`usesBrowserWorker: false`) and Browser Web Worker execution (`usesBrowserWorker: true`, which includes Worker lifecycle and `postMessage` structured-clone transfer) are reported as separate environments, not interchangeable baselines.
|
|
484
500
|
|
|
501
|
+
### Rebuilding HiGHS WebAssembly & Release Workflow
|
|
502
|
+
|
|
503
|
+
1. **Rebuilding / Updating HiGHS WebAssembly Assets (`highs.config.json`)**:
|
|
504
|
+
```bash
|
|
505
|
+
# Compile ERGO-Code/HiGHS to public/highs.wasm + runtime.js and update SHA-256 hashes in highs.config.json
|
|
506
|
+
npm run build:highs-wasm
|
|
507
|
+
|
|
508
|
+
# After merging to main, upload the updated assets to the highs-<version> GitHub Release tag
|
|
509
|
+
# so on-demand downloads (scripts/ensure-highs-wasm.mjs) match highs.config.json SHA-256 hashes:
|
|
510
|
+
gh release upload highs-v1.15.1 public/highs.wasm src/modeler/solvers/highs/runtime.js --clobber
|
|
511
|
+
```
|
|
512
|
+
Alternatively, trigger the **Build HiGHS WebAssembly** workflow (`.github/workflows/build-wasm.yml`) via `workflow_dispatch` with `create_release: true`, then download the `highs-wasm-assets` workflow artifact (`public/highs.wasm`, `src/modeler/solvers/highs/runtime.js`, and `highs.config.json`) and commit those updated files to `main` so repository checksums stay synchronized with the published Release assets.
|
|
513
|
+
|
|
514
|
+
2. **Publishing `@ohtaman/washi` to npm**:
|
|
515
|
+
- Merging to `main` automatically deploys the updated documentation and web demo to GitHub Pages (`.github/workflows/deploy-demo.yml`), but does **not** publish to npm automatically.
|
|
516
|
+
- To publish a new version to npm, bump `"version"` in `package.json` on `main` and publish a GitHub Release (e.g., `gh release create v0.5.1 --generate-notes`). Publishing the GitHub Release triggers `.github/workflows/publish-npm.yml`, which runs unit and Playwright distribution checks before publishing to npm via OIDC Trusted Publishing.
|
|
517
|
+
|
|
485
518
|
---
|
|
486
519
|
|
|
487
520
|
## 📄 License
|
|
488
521
|
|
|
489
522
|
- **`@ohtaman/washi`**: [MIT License](./LICENSE)
|
|
490
|
-
- **HiGHS** (default engine): MIT License
|
|
491
|
-
- **Z3** (optional plugin): MIT License
|
|
492
|
-
- **GLPK** (optional plugin): GPL-3.0 License
|
|
523
|
+
- **HiGHS** (default engine, [ERGO-Code/HiGHS](https://github.com/ERGO-Code/HiGHS)): MIT License
|
|
524
|
+
- **Z3** (optional plugin via [`z3-solver`](https://www.npmjs.com/package/z3-solver)): MIT License
|
|
525
|
+
- **GLPK** (optional plugin via [`glpk.js`](https://www.npmjs.com/package/glpk.js)): GPL-3.0 License
|
|
526
|
+
|
|
527
|
+
See [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md) for full attribution and license details of bundled/peer optimization engines.
|
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 -
|
|
5
|
+
<img alt="WaSHI - 适用于数理优化与约束编程的代数建模器 (TypeScript & JavaScript)" src="./assets/washi-header-light.png" width="420" />
|
|
6
6
|
</picture>
|
|
7
|
-
<p><strong
|
|
7
|
+
<p><strong>适用于数理优化与约束编程的代数建模器</strong></p>
|
|
8
8
|
<p>
|
|
9
9
|
<em>线性规划 (LP) • 混合整数规划 (MIP) • 凸二次规划 (QP) • SMT逻辑约束与冲突诊断</em>
|
|
10
10
|
</p>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
**WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) 是面向 TypeScript / JavaScript
|
|
27
|
+
**WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) 是面向 TypeScript / JavaScript 的数理优化与约束编程代数建模器,受到 Python **PuLP** 和 Julia **JuMP** 的启发。你可以在应用代码中定义变量、目标函数、算术约束和逻辑约束。WaSHI 负责构建模型、转换为求解器输入,并将结果映射回变量;优化与可满足性检查由 **HiGHS**、**Z3** 和 **GLPK** 完成。
|
|
28
28
|
|
|
29
29
|
HiGHS 是默认求解器;Z3 和 GLPK 是可选插件。软件包提供 Node.js 和浏览器分发版本,并包含 WebAssembly 资源。部署要求请参阅[浏览器使用说明](#-浏览器与-web-worker-使用指南)。
|
|
30
30
|
|
|
@@ -52,7 +52,8 @@ console.log(`生产计划: x=${x.value}, y=${y.value} (最大利润: $${m.object
|
|
|
52
52
|
1. **代数模型构建**:使用领域变量构造函数(`m.binary`、`m.integer`、`m.continuous`)、标签模板字面量(`expr`)、向量聚合函数(`dot`、`sum`)以及一等约束(`m.constraint`)构建优化模型。由于 JavaScript 不支持运算符重载,`` expr`...` `` 采用类似参数化 SQL 模板的方式,在解析中缀数学运算符(`+`、`-`、`*`、`^2`、`<=`、`>=`、`==`)的同时,将 `${...}` 插值直接绑定为强类型的 `Var` 或表达式对象引用,从而保留静态类型检查、IDE 重命名支持以及多维索引访问(`${flow[i][j]}`)。
|
|
53
53
|
2. **求解器适配器**:通过共同的建模 API 使用 HiGHS、Z3 或 GLPK,也可以[注册自己的适配器](https://github.com/ohtaman/washi/blob/main/docs/zh/solvers/custom-solver.md)。需要选择支持相应问题类型的求解器;不同求解器的能力并不相同。
|
|
54
54
|
3. **本地执行与 WebAssembly 分发**:使用本地求解器适配器时,可在应用内直接求解,无需单独的 Python 服务或本地 C/C++ 编译——这消除了在快速开发和交付交互式工具时的后端基础设施瓶颈,也便于在客户端直接与浏览器内 LLM(如 WebGPU / WebLLM)协同工作。浏览器部署需要包含生成的 JS、Worker 和 WASM 资源。离线使用还需要这些资源可在本地访问或已缓存。Z3 有额外的浏览器隔离要求。
|
|
55
|
-
4.
|
|
55
|
+
4. **命名约束与冲突诊断**:通过可满足性检查(`m.check()`),可调查矛盾约束(`conflicts` / `unsatCore`)以排查不可行性原因:内置 HiGHS 分离出**弹性修复集合**(`conflicts`,恢复可行性所需松弛的约束集合),而 Z3 提取 **SMT 不可满足核心**(`unsatCore` / `conflicts`,相互矛盾的约束子集;不保证最小性)。
|
|
56
|
+
5. **高级分解方法编排**:利用一等分解算法(`master.solveColumnGeneration`、`master.solveBenders`),突破单体 MIP 在特定结构(下料问题、车辆路径/VRP、旅行商/TSP、两阶段设施选址规划等)上的搜索树爆炸瓶颈。结合定价子问题(Pricing)与链接约束(`sub.link(...)`)的清晰回调编排,协同对偶定价、割平面生成与整数解复原。
|
|
56
57
|
|
|
57
58
|
模型构建与转换由 WaSHI 负责。支持的问题类型、数值行为和求解时间取决于所选求解器、配置及具体问题。建模开销与求解器执行时间应分别测量;某个模型上的结果并不构成通用性能保证。
|
|
58
59
|
|
|
@@ -62,9 +63,9 @@ console.log(`生产计划: x=${x.value}, y=${y.value} (最大利润: $${m.object
|
|
|
62
63
|
|
|
63
64
|
| 适配器 | 引擎许可证 | 支持的问题类型 | 引擎作用 | 集成方式 |
|
|
64
65
|
| :--- | :--- | :--- | :--- | :--- |
|
|
65
|
-
| **HiGHS** | **MIT** | **LP, MIP, 凸QP** | 数值优化 | 默认内置 |
|
|
66
|
-
| **Z3** | **MIT** | **SMT, SAT, 逻辑, MIP** | 可满足性检查、Unsat Core、优化 | 可选插件 (`@ohtaman/washi/solvers/z3`) |
|
|
67
|
-
| **GLPK** | **GPL-3.0** | **LP, MIP** | 线性与混合整数优化 | 可选插件 (`@ohtaman/washi/solvers/glpk`) |
|
|
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`) |
|
|
68
69
|
| **Mock** | **MIT** | — | 为集成测试提供模拟响应 | 内置;不实际求解模型 |
|
|
69
70
|
|
|
70
71
|
---
|
|
@@ -92,9 +93,13 @@ npm install z3-solver # 用于 SMT 与冲突诊断
|
|
|
92
93
|
npm install glpk.js # 用于 GLPK 求解器 (GPL-3.0)
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
*(可选)* 面向 AI 编程助手(Claude Code、Antigravity、Cursor、Codex
|
|
96
|
+
*(可选)* 面向 AI 编程助手(Claude Code、Antigravity、Cursor、Codex 等),可以通过 `skills` CLI 或随包附带的 [`skills/washi/SKILL.md`](skills/washi/SKILL.md) 引入建模与校验技能:
|
|
96
97
|
|
|
97
98
|
```bash
|
|
99
|
+
# 通过 skills CLI (skills.sh / vercel-labs/skills) 安装
|
|
100
|
+
npx skills add ohtaman/washi
|
|
101
|
+
|
|
102
|
+
# 或将随包附带的技能手动复制到项目中
|
|
98
103
|
mkdir -p .agents/skills/washi
|
|
99
104
|
cp node_modules/@ohtaman/washi/skills/washi/SKILL.md .agents/skills/washi/SKILL.md
|
|
100
105
|
```
|
|
@@ -224,15 +229,16 @@ console.log(`警报响起? ${m.values.get("siren")}`); // true
|
|
|
224
229
|
|
|
225
230
|
---
|
|
226
231
|
|
|
227
|
-
### 4.
|
|
232
|
+
### 4. 冲突诊断 (`conflicts` / `unsatCore`)
|
|
228
233
|
|
|
229
|
-
|
|
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`),返回相互矛盾的约束子集。
|
|
230
237
|
|
|
231
238
|
```ts
|
|
232
239
|
import { Model, expr } from "@ohtaman/washi";
|
|
233
|
-
import "@ohtaman/washi/solvers/z3";
|
|
234
240
|
|
|
235
|
-
const m = new Model(
|
|
241
|
+
const m = new Model("ConflictDiagnosis");
|
|
236
242
|
const engineers = m.integer("engineers", { lb: 0, ub: 20 });
|
|
237
243
|
const budget = m.continuous("budget", { lb: 0, ub: 100000 });
|
|
238
244
|
const rushDelivery = m.bool("rushDelivery");
|
|
@@ -252,12 +258,18 @@ m.constraint(expr`${budget} <= 50000`, "strict_board_budget_cap");
|
|
|
252
258
|
// 规则 5: 最低 1 名员工用工底线(无关规则)
|
|
253
259
|
m.constraint(expr`${engineers} >= 1`, "minimum_one_employee");
|
|
254
260
|
|
|
255
|
-
|
|
261
|
+
// 1. 使用默认 HiGHS 进行弹性修复诊断
|
|
262
|
+
const res = await m.check();
|
|
256
263
|
|
|
257
264
|
console.log(`求解状态: ${res.status}`); // "Unsat"
|
|
258
|
-
console.log("
|
|
259
|
-
// 输出: ["
|
|
260
|
-
//
|
|
265
|
+
console.log("修复约束集合(需松弛的约束):", res.conflicts);
|
|
266
|
+
// HiGHS 输出: ["rush_required"]
|
|
267
|
+
// (松弛 rush_required 即可恢复可行性;无关的 minimum_one_employee 不受影响)
|
|
268
|
+
|
|
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"]
|
|
261
273
|
```
|
|
262
274
|
|
|
263
275
|
---
|
|
@@ -410,7 +422,7 @@ WaSHI 采用完全解耦的插件式求解器架构。你可以轻松编写并
|
|
|
410
422
|
完整文档可在 **[ohtaman.github.io/washi/zh/](https://ohtaman.github.io/washi/zh/)** 及仓库的 [`docs/zh/`](docs/zh/)([英文版 `docs/`](docs/))中查阅:
|
|
411
423
|
|
|
412
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)
|
|
413
|
-
- **建模指南**: [决策变量 (`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)
|
|
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)
|
|
414
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)
|
|
415
427
|
|
|
416
428
|
---
|
|
@@ -426,6 +438,8 @@ WaSHI 采用完全解耦的插件式求解器架构。你可以轻松编写并
|
|
|
426
438
|
| **基础模型** | [营养问题与灵敏度分析](https://github.com/ohtaman/washi/blob/main/examples/node/10-diet-sensitivity.ts) | 影子价格 (`constr.dual`)、松弛量 (`constr.slack`) 与缩减成本 (`var.reducedCost`) | HiGHS |
|
|
427
439
|
| **实战应用** | [员工排班与冲突诊断](https://github.com/ohtaman/washi/blob/main/examples/node/11-shift-scheduling.ts) | 周排班优化与周六休假冲突诊断 | HiGHS + Z3 |
|
|
428
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 |
|
|
429
443
|
| **实战应用** | [投资组合分配](https://github.com/ohtaman/washi/blob/main/examples/node/03-portfolio-qp.ts) | 凸二次目标函数 (`QuadExpr`) 与分配约束 | HiGHS |
|
|
430
444
|
| **逻辑 / SMT** | [业务规则检查](https://github.com/ohtaman/washi/blob/main/examples/node/04-smt-security-rules.ts) | 算术与逻辑约束 (`bool`, `implies`) 的可满足性检查 | Z3 |
|
|
431
445
|
| **逻辑 / SMT** | [冲突诊断](https://github.com/ohtaman/washi/blob/main/examples/node/05-unsat-core-diagnosis.ts) | 命名约束与 Unsat Core (`unsatCore`) | Z3 |
|
|
@@ -443,6 +457,8 @@ npx tsx examples/node/09-transportation-problem.ts
|
|
|
443
457
|
npx tsx examples/node/10-diet-sensitivity.ts
|
|
444
458
|
npx tsx examples/node/11-shift-scheduling.ts
|
|
445
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
|
|
446
462
|
|
|
447
463
|
# 本地浏览器演示: http://localhost:5173/demo/
|
|
448
464
|
npm run dev
|
|
@@ -482,11 +498,30 @@ node scripts/run-benchmarks.mjs --browser
|
|
|
482
498
|
- **明确的测量边界**:将冷启动初始化(`coldRuntimeInitMs`、`coldFirstSolveMs`)与复用运行时的重复测量(`modelBuildMs`、`validationMs`、LP 字符串适配器的 `lpSerializationMs` 或结构化适配器的 `symbolMapMs`、基于 `MockSolver` 的 `resultMappingMs`、`adapterSolveMs` 以及 `endToEndSolveMs`)分开直接测量,不通过相减来臆造“原生求解器时间”。
|
|
483
499
|
- **区分不同执行环境**:Node.js 进程内 WASM(`usesBrowserWorker: false`)与浏览器 Web Worker 执行(`usesBrowserWorker: true`,包含 Worker 生命周期与 `postMessage` 结构化克隆传输)作为不同执行环境分别报告,不可直接互换作基线。
|
|
484
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。
|
|
517
|
+
|
|
485
518
|
---
|
|
486
519
|
|
|
487
520
|
## 📄 许可证
|
|
488
521
|
|
|
489
522
|
- **`@ohtaman/washi`**: [MIT 许可证](./LICENSE)
|
|
490
|
-
- **HiGHS
|
|
491
|
-
- **Z3
|
|
492
|
-
- **GLPK
|
|
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)。
|
package/THIRD_PARTY_LICENSES.md
CHANGED
|
@@ -9,15 +9,14 @@ Depending on the solver you choose at runtime, WaSHI interacts with the followin
|
|
|
9
9
|
## 1. HiGHS (Default Solver)
|
|
10
10
|
|
|
11
11
|
- **Role**: Default Linear & Mixed-Integer Programming Engine (WebAssembly)
|
|
12
|
-
- **Package**: [`highs`](https://www.npmjs.com/package/highs)
|
|
13
12
|
- **License**: **MIT License**
|
|
14
|
-
- **Upstream Repository**: [ERGO-Code/HiGHS](https://github.com/ERGO-Code/HiGHS)
|
|
13
|
+
- **Upstream Repository**: [ERGO-Code/HiGHS](https://github.com/ERGO-Code/HiGHS)
|
|
14
|
+
- **Compilation**: Directly compiled from official upstream source to WebAssembly via native C API (`highs_c_api.h`)
|
|
15
15
|
|
|
16
16
|
```text
|
|
17
17
|
MIT License
|
|
18
18
|
|
|
19
|
-
Copyright (c)
|
|
20
|
-
Copyright (c) 2026 HiGHS
|
|
19
|
+
Copyright (c) 2026 ERGO-Code / HiGHS developers
|
|
21
20
|
|
|
22
21
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
23
22
|
of this software and associated documentation files (the "Software"), to deal
|
|
File without changes
|