@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.
- package/README.ja.md +103 -421
- package/README.md +103 -421
- package/README.zh-CN.md +103 -421
- package/THIRD_PARTY_LICENSES.md +5 -3
- package/dist/browser/solvers/glpk.js +2 -2
- package/dist/browser/solvers/glpk.min.js +1 -1
- package/dist/browser/washi.js +777 -261
- package/dist/browser/washi.min.js +3 -3
- package/dist/lib/{registry-C20sxTwm.js → registry-D7TZ3Wh_.js} +88 -18
- package/dist/lib/solvers/glpk.js +3 -3
- package/dist/lib/solvers/z3.js +1 -1
- package/dist/lib/washi.js +864 -421
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modeler/expression.d.ts +47 -26
- package/dist/types/modeler/expression.d.ts.map +1 -1
- package/dist/types/modeler/index.d.ts +2 -2
- package/dist/types/modeler/index.d.ts.map +1 -1
- package/dist/types/modeler/model.d.ts +12 -6
- package/dist/types/modeler/model.d.ts.map +1 -1
- package/dist/types/modeler/parser.d.ts +25 -5
- package/dist/types/modeler/parser.d.ts.map +1 -1
- package/dist/types/modeler/solvers/glpk/solver.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/solver.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/worker-client.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/docs/examples/diet-sensitivity.md +15 -14
- package/docs/examples/ecommerce-coupons.md +15 -22
- package/docs/examples/index.md +14 -12
- package/docs/examples/knapsack.md +8 -7
- package/docs/examples/portfolio-qp.md +11 -4
- package/docs/examples/production.md +4 -4
- package/docs/examples/shift-scheduling.md +20 -7
- package/docs/examples/smt-security.md +16 -4
- package/docs/examples/transportation.md +46 -19
- package/docs/examples/traveling-salesperson.md +28 -44
- package/docs/examples/unsat-core.md +15 -5
- package/docs/examples/vehicle-routing.md +10 -8
- package/docs/getting-started/ai-agents.md +25 -14
- package/docs/getting-started/cross-origin.md +56 -28
- package/docs/getting-started/index.md +40 -69
- package/docs/getting-started/runtimes.md +66 -61
- package/docs/guide/constraints.md +46 -40
- package/docs/guide/decomposition.md +127 -259
- package/docs/guide/expressions.md +90 -39
- package/docs/guide/formulation-tips.md +212 -0
- package/docs/guide/objectives.md +7 -4
- package/docs/guide/unsat-core.md +18 -6
- package/docs/guide/variables.md +33 -38
- package/docs/ja/getting-started/ai-agents.md +24 -14
- package/docs/solvers/highs.md +27 -6
- package/docs/solvers/index.md +1 -1
- package/docs/solvers/z3.md +3 -0
- package/docs/zh/getting-started/ai-agents.md +24 -14
- package/llms-full.txt +929 -687
- package/llms.txt +21 -19
- package/package.json +3 -3
- 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 -
|
|
5
|
+
<img alt="WaSHI - TypeScript 数理最適化モデラー" src="./assets/washi-header-light.png" width="420" />
|
|
6
6
|
</picture>
|
|
7
|
-
<p><strong
|
|
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.
|
|
20
|
-
<a href="https://ohtaman.
|
|
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**
|
|
27
|
+
**WaSHI**(WebAssembly-backed, Solver-independent, High-level modeling Interface)は、Python の **PuLP** に着想を得た、数理最適化と制約プログラミングのための TypeScript / JavaScript 向け代数モデラーです。変数・目的関数・制約をアプリケーションコードで記述し、Node.js やブラウザ上で **HiGHS**(標準)・**Z3**・**GLPK** を使ってそのまま求解できます。
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
## ✨ 主な特徴
|
|
30
30
|
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
80
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
157
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
GNU Linear Programming Kit (GLPK) ソルバープラグインを利用する場合:
|
|
89
|
+
## 🚀 基本的な使い方
|
|
280
90
|
|
|
281
|
-
|
|
282
|
-
import { Model, expr, maximize } from "@ohtaman/washi";
|
|
283
|
-
import "@ohtaman/washi/solvers/glpk";
|
|
91
|
+
### 1. 総和・内積(`sum` / `dot`)と条件付き制約
|
|
284
92
|
|
|
285
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
121
|
+
線形制約のもとで二次の目的関数を最小化:
|
|
330
122
|
|
|
331
|
-
|
|
123
|
+
```ts
|
|
124
|
+
import { Model, expr, minimize } from "@ohtaman/washi";
|
|
332
125
|
|
|
333
|
-
|
|
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
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
134
|
+
await m.solve();
|
|
135
|
+
console.log(`Tech: ${x.value?.toFixed(2)}, Bonds: ${y.value?.toFixed(2)}`);
|
|
136
|
+
```
|
|
343
137
|
|
|
344
|
-
###
|
|
138
|
+
### 3. SMT 論理ルール & 矛盾診断 (`m.check`)
|
|
345
139
|
|
|
346
|
-
|
|
140
|
+
論理条件(`m.bool`, `implies`)を含むモデルの充足可能性を判定し、矛盾時の原因制約を特定します:
|
|
141
|
+
- **HiGHS(標準)**: 緩和すれば実行可能になる**修復集合**(`res.conflicts`)を特定します。
|
|
142
|
+
- **Z3**: 相互に矛盾している**充足不能コア**(`res.unsatCore` / `res.conflicts`)を抽出します。
|
|
347
143
|
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
164
|
+
---
|
|
371
165
|
|
|
372
|
-
|
|
166
|
+
## 🌐 ブラウザ & Web Worker での利用方法
|
|
373
167
|
|
|
374
|
-
|
|
375
|
-
-
|
|
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
|
|
382
|
-
import "./washi/solvers/glpk.js"
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
393
|
-
|
|
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
|
-
>
|
|
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
|
-
|
|
191
|
+
ローカル開発、テスト・ベンチマークの実行、WebAssembly アセットの再ビルド、およびリリース手順については [CONTRIBUTING.md](./CONTRIBUTING.md) を参照してください。
|
|
417
192
|
|
|
418
193
|
---
|
|
419
194
|
|
|
420
|
-
##
|
|
195
|
+
## 🙏 謝辞
|
|
421
196
|
|
|
422
|
-
|
|
197
|
+
WaSHI は、数理最適化および自動推論分野の素晴らしいオープンソースソフトウェアの上に成り立っています:
|
|
423
198
|
|
|
424
|
-
-
|
|
425
|
-
-
|
|
426
|
-
-
|
|
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
|
-
-
|
|
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) を参照してください。
|