@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/llms.txt
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> WaSHI: WebAssembly-backed Algebraic Modeler for Mathematical Optimization & Constraint Programming (LP, MIP, QP, SMT)
|
|
4
4
|
|
|
5
|
-
WaSHI brings the algebraic modeling style of Python's **PuLP**
|
|
5
|
+
**WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) brings the algebraic modeling style of Python's **PuLP** to the TypeScript and JavaScript ecosystem.
|
|
6
6
|
|
|
7
7
|
- Full single-file documentation reference: [llms-full.txt](llms-full.txt)
|
|
8
8
|
- Canonical AI agent modeling quick-reference: [docs/getting-started/ai-agents.md](docs/getting-started/ai-agents.md)
|
|
@@ -52,7 +52,7 @@ import "@ohtaman/washi/solvers/glpk";
|
|
|
52
52
|
1. **Bundled WASM by default (no implicit CDN fallback)**:
|
|
53
53
|
- In Node.js and modern bundlers, WebAssembly assets resolve relative to the module automatically.
|
|
54
54
|
- In browser deployments, deploy the full `dist/browser/` directory (JS, Worker, and `.wasm` files) together. If a local WASM URL is missing or returns an HTML SPA fallback, initialization fails immediately and reports the attempted URL—it **never** silently switches to a public CDN.
|
|
55
|
-
- In browser runtimes, to load `highs.wasm` from a custom location, call `setHighsWasmUrl("https://.../highs.wasm")` or pass `await m.solve({ wasmUrl: "https://.../highs.wasm" })` (ignored in Node.js, which always loads
|
|
55
|
+
- In browser runtimes, to load `highs.wasm` from a custom location, call `setHighsWasmUrl("https://.../highs.wasm")` or pass `await m.solve({ wasmUrl: "https://.../highs.wasm" })` (ignored in Node.js, which always loads WaSHI's bundled local `highs.wasm` runtime).
|
|
56
56
|
2. **Z3 requires a Secure Context, Cross-Origin Isolation, and CORS in browsers**:
|
|
57
57
|
- Z3 WebAssembly uses `SharedArrayBuffer` multithreading. Browser pages running Z3 must run in a secure context (`window.isSecureContext === true`, i.e., HTTPS or `localhost`) and be cross-origin isolated (`window.crossOriginIsolated === true`) by serving:
|
|
58
58
|
- `Cross-Origin-Opener-Policy: same-origin` (on the document)
|
|
@@ -61,7 +61,7 @@ import "@ohtaman/washi/solvers/glpk";
|
|
|
61
61
|
- Importing `@ohtaman/washi` never auto-injects a Service Worker. When a secure context or cross-origin isolation is absent in a browser, Z3 rejects immediately with a descriptive error.
|
|
62
62
|
3. **Web Workers & Cancellation (`AbortSignal`)**:
|
|
63
63
|
- Pre-solve cancellation (`signal.aborted` before execution starts) is supported across all solvers.
|
|
64
|
-
- In browsers where `Worker` is available, HiGHS runs in a dedicated Web Worker by default (`useWorker: true`). Passing `{ signal }` to `m.solve({ signal })` preemptively terminates an in-flight Worker solve (or cancels queued Worker requests).
|
|
64
|
+
- In browsers where `Worker` is available on a non-opaque effective origin (`window.origin !== "null"`), HiGHS runs in a dedicated Web Worker by default (`useWorker: true`). On opaque effective origins (`window.origin === "null"`, such as `file:` URLs or `sandbox="allow-scripts"` `<iframe>` embeds without `allow-same-origin`), HiGHS defaults to main-thread execution (`useWorker: false`). Passing `{ signal }` to `m.solve({ signal })` preemptively terminates an in-flight Worker solve (or cancels queued Worker requests).
|
|
65
65
|
- On main-thread HiGHS (`useWorker: false` or in Node.js), cooperative mid-solve cancellation is supported when `abort()` is triggered synchronously inside an `onProgress` callback at a solver interrupt checkpoint; arbitrary asynchronous aborts from outside cannot preempt a blocked synchronous WASM thread until a callback checkpoint or completion. Single-threaded WASM solvers without interrupt hooks (GLPK, Z3) check `signal` before execution starts.
|
|
66
66
|
|
|
67
67
|
---
|
|
@@ -77,6 +77,7 @@ const m = new Model("ExampleModel");
|
|
|
77
77
|
|
|
78
78
|
// Scalar variables
|
|
79
79
|
const x = m.continuous("x", { lb: 0, ub: 100 });
|
|
80
|
+
const y = m.continuous("y", { lb: 0, ub: 100 });
|
|
80
81
|
const n = m.integer("n", { lb: 0, ub: 10 });
|
|
81
82
|
const b = m.binary("b");
|
|
82
83
|
const flag = m.bool("flag"); // Propositional boolean (for Z3 / logical constraints)
|
|
@@ -98,12 +99,12 @@ const mixed = m.binary(["A", "B"] as const, 3); // Record<"A" | "B", Var[]>
|
|
|
98
99
|
### Step 2: Build Expressions (`expr`, `sum`, `dot`)
|
|
99
100
|
|
|
100
101
|
- **Unified `expr` template tag**:
|
|
101
|
-
- Linear expression (`LinExpr`): `` expr`30 * ${x} + 50 * ${n} - 10` ``
|
|
102
|
-
- Quadratic expression (`QuadExpr`): `` expr`${x}^2 + 2 * ${x} * ${
|
|
103
|
-
- Linear constraint (`Constraint`): `` expr`${x} + 2 * ${n} <= 40` `` (supports `<=`, `>=`, `==`, and `=`).
|
|
104
|
-
- **Aggregations**:
|
|
105
|
-
- `sum(
|
|
106
|
-
- `dot(a, b)` computes the inner product of matching 1D arrays, 2D arrays (`number[][]` / `Var[][]
|
|
102
|
+
- Linear expression (`LinExpr`): `` expr`30 * ${x} + 50 * ${n} - 10` ``, `` expr`dot(${profit}, ${byItem}) - 20 * ${b}` ``, `` expr`sum((${price} - ${cost}) * ${byItem})` ``
|
|
103
|
+
- Quadratic expression (`QuadExpr`): `` expr`${x}^2 + 2 * ${x} * ${y} + ${y}^2` ``, `` expr`sum((${vec} - ${target})^2)` `` (supported for convex QP objectives on purely continuous models using `m.continuous`; built-in HiGHS does not support MIQP models containing integer, binary, or boolean variables).
|
|
104
|
+
- Linear constraint (`Constraint`): `` expr`${x} + 2 * ${n} <= 40` ``, `` expr`sum(${byItem}) <= 100` `` (supports `<=`, `>=`, `==`, and `=`).
|
|
105
|
+
- **Aggregations & Element-Wise Container Arithmetic**:
|
|
106
|
+
- `sum(containerOrItems, mapper?)` (usable inside `` expr`sum(...)` `` or standalone `sum(...)`) sums a 1D/2D `Array`, `Iterable`, or plain `Record` of `Var` / `LinExpr` / `number` (without needing `Object.values(record)`), or maps over items/counts via `sum(items, (item, i) => ...)`. Inside `` expr`sum(...)` ``, element-wise container arithmetic (`+`, `-`, `*`, `/`, `^2`) is also supported.
|
|
107
|
+
- `dot(a, b)` (usable inside `` expr`dot(${a}, ${b})` `` or standalone `dot(a, b)`) computes the inner product of matching 1D arrays, 2D arrays (`number[][]` / `Var[][]`, computing the Frobenius inner product $\sum_{i,j} A_{i,j} B_{i,j}$), plain records (`Record<string, ...>`), or mixed Array/Record containers in either operand order.
|
|
107
108
|
- **Fluent methods**:
|
|
108
109
|
- Arithmetic (on `LinExpr` and `QuadExpr`; `Var` supports `.add()`, `.sub()`, `.mul()`, `.neg()`): `.add(other)`, `.sub(other)`, `.mul(other)`, `.div(scalar)`, `.neg()`
|
|
109
110
|
- Comparisons (on `Var` and `LinExpr`): `.le(rhs, name?)`, `.ge(rhs, name?)`, `.eq(rhs, name?)`
|
|
@@ -117,8 +118,8 @@ Constructing an `expr` or `.le()` object does **not** attach it to the model unt
|
|
|
117
118
|
// Set objective using maximize() or minimize()
|
|
118
119
|
m.objective(maximize(expr`30 * ${x} + 50 * ${n}`));
|
|
119
120
|
|
|
120
|
-
// Register constraints on the model
|
|
121
|
-
m.constraint(expr`${x} + 2 * ${n} <= 40`, "resource_limit");
|
|
121
|
+
// Register constraints on the model (returns the registered Constraint / BoolExpr or array)
|
|
122
|
+
const limit = m.constraint(expr`${x} + 2 * ${n} <= 40`, "resource_limit");
|
|
122
123
|
|
|
123
124
|
// Indicator constraint (MIP Big-M reformulation: b === 1 => x <= 50)
|
|
124
125
|
m.indicator(b, expr`${x} <= 50`, { activeValue: 1, name: "cap_when_b" });
|
|
@@ -164,23 +165,24 @@ m.indicator(b, expr`${x} <= 50`, { activeValue: 1, name: "cap_when_b" });
|
|
|
164
165
|
### Getting Started
|
|
165
166
|
|
|
166
167
|
- [AI Coding Agent Quick-Reference Guide](docs/getting-started/ai-agents.md): This document is the **consumer modeling quick-reference** for AI coding agents and developers building optimization or satisfiability models with `@ohtaman/washi`.
|
|
167
|
-
- [Introduction & Installation](docs/getting-started/index.md): WaSHI brings the algebraic modeling style of Python's **PuLP**
|
|
168
|
-
- [Runtime Environments & Deployment](docs/getting-started/runtimes.md): WaSHI runs across JavaScript and TypeScript runtimes—from Node.js, Bun, and Deno to modern bundlers, vanilla browser `<script>` tags
|
|
169
|
-
- [Cross-Origin Isolation (Z3 & Browsers)](docs/getting-started/cross-origin.md): When running the **Z3** solver
|
|
168
|
+
- [Introduction & Installation](docs/getting-started/index.md): **WaSHI** (WebAssembly-backed, Solver-independent, High-level modeling Interface) brings the algebraic modeling style of Python's **PuLP** to the TypeScript and JavaScript ecosystem.
|
|
169
|
+
- [Runtime Environments & Deployment](docs/getting-started/runtimes.md): WaSHI runs across JavaScript and TypeScript runtimes—from Node.js, Bun, and Deno to modern bundlers, static hosting, and vanilla browser `<script>` tags—without native C/C++ compilation.
|
|
170
|
+
- [Cross-Origin Isolation (Z3 & Browsers)](docs/getting-started/cross-origin.md): When running the **Z3** solver inside a web browser, Cross-Origin Isolation HTTP headers are required so the browser enables `SharedArrayBuffer`.
|
|
170
171
|
|
|
171
172
|
### Modeling Guide
|
|
172
173
|
|
|
173
|
-
- [Variables & Domains](docs/guide/variables.md): Variables represent the mathematical decision variables in your optimization model.
|
|
174
|
+
- [Variables & Domains](docs/guide/variables.md): Variables represent the mathematical decision variables in your optimization or logical model.
|
|
174
175
|
- [Expressions (`expr`, `sum`, `dot`)](docs/guide/expressions.md): Mathematical expressions are linear or quadratic combinations of decision variables and numeric coefficients.
|
|
175
176
|
- [Constraints (`m.constraint` & `m.indicator`)](docs/guide/constraints.md): Constraints restrict the feasible solution space of your mathematical or logical model.
|
|
176
177
|
- [Objectives & Solving (`m.solve` & `m.check`)](docs/guide/objectives.md): The objective function defines the goal of mathematical optimization—whether to maximize profits, minimize costs, or minimize quadratic risk variance.
|
|
177
|
-
- [Conflict Diagnosis (`unsatCore`) & Solution Validation](docs/guide/unsat-core.md): WaSHI provides built-in tools for both: **
|
|
178
|
-
- [
|
|
178
|
+
- [Conflict Diagnosis (`unsatCore`) & Solution Validation](docs/guide/unsat-core.md): WaSHI provides built-in tools for both: **conflict diagnosis** via built-in HiGHS elastic relaxation or Z3 Unsat Core (`m.check()`), **independent solution validation** (`m.validateSolution()`), **LP formulation export** (`m.toLpString()`), and **fast unit testing** (`MockSolver`).
|
|
179
|
+
- [Decomposition Methods (`solveColumnGeneration` & `solveBenders`)](docs/guide/decomposition.md): When monolithic Mixed-Integer Programming (MIP) models have exponentially many candidate patterns or large multi-stage subproblems, WaSHI provides two high-level decomposition orchestrators—`master.solveColumnGeneration()` and `master.solveBenders()`—along with low-level primitives for dual inspection and dynamic model updates.
|
|
180
|
+
- [Formulation Patterns & Optimization Tips](docs/guide/formulation-tips.md): While the preceding Modeling Guide pages cover WaSHI's APIs (`Model`, `expr`, `m.constraint`, `m.solve`, etc.), this page collects standard mathematical optimization formulation patterns and solver tuning techniques frequently used in linear and mixed-integer programming (LP/MIP).
|
|
179
181
|
|
|
180
182
|
### Solvers
|
|
181
183
|
|
|
182
184
|
- [Solvers Overview](docs/solvers/index.md): WaSHI is designed around a pluggable, decoupled solver architecture.
|
|
183
|
-
- [HiGHS Solver Engine](docs/solvers/highs.md): **HiGHS** is high-performance mathematical optimization software
|
|
185
|
+
- [HiGHS Solver Engine](docs/solvers/highs.md): **HiGHS** is high-performance mathematical optimization software initiated at the University of Edinburgh (highs.dev · ERGO-Code/HiGHS).
|
|
184
186
|
- [Z3 SMT Solver Engine](docs/solvers/z3.md): **Z3** is a theorem prover and Satisfiability Modulo Theories (SMT) solver developed by Microsoft Research.
|
|
185
187
|
- [GLPK Solver Engine](docs/solvers/glpk.md): The **GNU Linear Programming Kit (GLPK)** is a long-standing, robust simplex and interior-point solver package intended for solving large-scale linear programming (LP) and mixed integer programming (MIP).
|
|
186
188
|
- [WaSHI Custom Solver Developer Guide](docs/solvers/custom-solver.md): This guide describes how to build, test, and distribute custom solver plugins for **WaSHI** (`@ohtaman/washi`).
|
|
@@ -196,6 +198,6 @@ m.indicator(b, expr`${x} <= 50`, { activeValue: 1, name: "cap_when_b" });
|
|
|
196
198
|
- [E-Commerce Cart & Coupon Optimizer (Indicator MIP)](docs/examples/ecommerce-coupons.md): Modern e-commerce checkouts often feature complex promotional rules: minimum spend thresholds, category-specific discounts, stackable vs. mutually exclusive coupons, and maximum coupon limits per order.
|
|
197
199
|
- [Portfolio Optimization (QP)](docs/examples/portfolio-qp.md): The Markowitz mean-variance portfolio optimization problem is the foundation of modern quantitative finance: allocate capital across risky assets to minimize overall portfolio variance (risk) subject to achieving a minimum required expected return.
|
|
198
200
|
- [SMT Security Policies](docs/examples/smt-security.md): Satisfiability Modulo Theories (SMT) combines propositional logic (Boolean SAT) with first-order theories (linear integer arithmetic, real inequalities).
|
|
199
|
-
- [Conflict Diagnosis (Unsat Core)](docs/examples/unsat-core.md): When business rules, budgets, and operational policies grow complex, constraints
|
|
201
|
+
- [Conflict Diagnosis (Unsat Core)](docs/examples/unsat-core.md): When business rules, budgets, and operational policies grow complex, constraints can easily conflict.
|
|
200
202
|
- [Capacitated Vehicle Routing Problem (CVRP, 50 Customers via Column Generation)](docs/examples/vehicle-routing.md): The **Capacitated Vehicle Routing Problem (CVRP)** determines the minimum number of delivery vehicles needed to visit a set of customers, subject to vehicle cargo capacity, maximum customer stops per shift, and route duration limits.
|
|
201
203
|
- [Traveling Salesperson Problem (TSP via Benders Decomposition)](docs/examples/traveling-salesperson.md): The **Traveling Salesperson Problem (TSP)** seeks the shortest closed tour that visits every city in a given set once and returns to the starting city.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ohtaman/washi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "WaSHI: WebAssembly-backed Algebraic Modeler for Mathematical Optimization & Constraint Programming (LP, MIP, QP, SMT)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/lib/washi.js",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"prepublishOnly": "node scripts/ensure-highs-wasm.mjs && npm run build:types && npm run build:lib && npm run build:browser && npm run build:llms",
|
|
84
84
|
"build:browser": "node scripts/ensure-highs-wasm.mjs && node scripts/build-browser.mjs",
|
|
85
85
|
"test:distribution": "node scripts/ensure-highs-wasm.mjs && npm run build:types && npm run build:lib && npm run build:browser && npm run build:llms && node --experimental-vm-modules scripts/check-distribution.mjs",
|
|
86
|
-
"test:demo": "BASE_URL=/
|
|
86
|
+
"test:demo": "BASE_URL=/ npm run build:demo && node scripts/check-demo-browser.mjs",
|
|
87
87
|
"bench": "node scripts/run-benchmarks.mjs"
|
|
88
88
|
},
|
|
89
89
|
"keywords": [
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"bugs": {
|
|
117
117
|
"url": "https://github.com/ohtaman/washi/issues"
|
|
118
118
|
},
|
|
119
|
-
"homepage": "https://
|
|
119
|
+
"homepage": "https://washi.ohtaman.dev/",
|
|
120
120
|
"dependencies": {},
|
|
121
121
|
"peerDependencies": {
|
|
122
122
|
"glpk.js": "^5.0.0",
|
package/skills/washi/SKILL.md
CHANGED
|
@@ -34,15 +34,15 @@ Select the solver engine and execution method that match the problem class:
|
|
|
34
34
|
- Indexed containers: pass a count (`number` -> `Var[]` / `Var[][]`) or key array (`readonly string[]` -> `Record<K, Var>` / `Record<R, Record<C, Var>>`).
|
|
35
35
|
- Provide finite `lb` and `ub` bounds whenever known—especially on variables used in `m.indicator()` so WaSHI can automatically derive a tight Big-M when `M` is omitted.
|
|
36
36
|
2. **Build expressions (`expr`, `sum`, `dot`)**:
|
|
37
|
-
- Linear expression (`LinExpr`): `` expr`30 * ${x} + 50 * ${y} - 10` ``
|
|
38
|
-
- Quadratic expression (`QuadExpr`, **objectives only**): `` expr`${x}^2 + 2 * ${x} * ${y} + ${y}^2` ``
|
|
39
|
-
- Linear constraint (`Constraint`): `` expr`${x} + 2 * ${y} <= 40` `` (supports `<=`, `>=`, `==`, `=`)
|
|
40
|
-
- Vector aggregations: `sum(
|
|
37
|
+
- Linear expression (`LinExpr`): `` expr`30 * ${x} + 50 * ${y} - 10` ``, `` expr`dot(${profit}, ${qty}) - 20 * ${lineOpen}` ``
|
|
38
|
+
- Quadratic expression (`QuadExpr`, **objectives only**): `` expr`${x}^2 + 2 * ${x} * ${y} + ${y}^2` ``, `` expr`sum((${xVec} - ${target})^2)` `` (purely continuous models on HiGHS; MIQP with integer/binary/boolean variables is not supported)
|
|
39
|
+
- Linear constraint (`Constraint`): `` expr`${x} + 2 * ${y} <= 40` ``, `` expr`sum(${qty}) <= 100` `` (supports `<=`, `>=`, `==`, `=`)
|
|
40
|
+
- Vector & Record aggregations: `sum(containerOrItems, mapper?)` and `dot(a, b)` (both usable inside `expr` or standalone; `sum` accepts 1D/2D `Array`, `Iterable`, and `Record` directly without `Object.values()`, plus element-wise container arithmetic `+`, `-`, `*`, `/`, `^2` inside `expr`; `dot` computes the 1D inner product or 2D Frobenius inner product)
|
|
41
41
|
- Propositional logic: `and(...)`, `or(...)`, `not(...)`, `implies(a, b)`, `xor(a, b)` (or fluent `.and()`, `.or()`, `.not()`, `.implies()`, `.xor()`). Automatically linearized into 0-1 MIP binary variables and linear constraints on HiGHS/GLPK, or solved natively on Z3.
|
|
42
42
|
3. **Register objective and named constraints**:
|
|
43
43
|
- Constructing an `expr` or `.le()` / `.ge()` / `.eq()` object does **not** attach it to the model.
|
|
44
44
|
- Register the objective with `m.objective(maximize(e))` or `m.objective(minimize(e))`.
|
|
45
|
-
- Register every constraint with a descriptive name: `m.constraint(c, "resource_limit")` or `m.indicator(binVar, c, { activeValue: 1, name: "cap_when_open" })`. Descriptive names are essential for LP inspection and conflict diagnosis (`conflicts` / `unsatCore`).
|
|
45
|
+
- Register every constraint with a descriptive name: `const limit = m.constraint(c, "resource_limit")` (returns the registered `Constraint` / `BoolExpr`, or array for batch inputs) or `m.indicator(binVar, c, { activeValue: 1, name: "cap_when_open" })`. Descriptive names are essential for LP inspection and conflict diagnosis (`conflicts` / `unsatCore`).
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
@@ -88,10 +88,10 @@ export async function solveAndVerifyMip() {
|
|
|
88
88
|
const qty = m.integer(products, { lb: 0, ub: 100 });
|
|
89
89
|
const lineOpen = m.binary("lineOpen");
|
|
90
90
|
|
|
91
|
-
m.objective(maximize(expr
|
|
92
|
-
m.constraint(expr
|
|
93
|
-
m.constraint(expr
|
|
94
|
-
m.indicator(lineOpen, expr
|
|
91
|
+
m.objective(maximize(expr`dot(${profit}, ${qty}) - 20 * ${lineOpen}`));
|
|
92
|
+
m.constraint(expr`dot(${woodPerUnit}, ${qty}) <= 40`, "wood_limit");
|
|
93
|
+
m.constraint(expr`dot(${laborPerUnit}, ${qty}) <= 50`, "labor_limit");
|
|
94
|
+
m.indicator(lineOpen, expr`sum(${qty}) <= 0`, {
|
|
95
95
|
activeValue: 0,
|
|
96
96
|
name: "closed_line_zero_output",
|
|
97
97
|
});
|
|
@@ -191,7 +191,11 @@ export async function diagnoseAndVerifyWithZ3() {
|
|
|
191
191
|
|
|
192
192
|
## 6. Guardrails & Common Pitfalls
|
|
193
193
|
|
|
194
|
-
- **No quadratic constraints**: Quadratic terms (`${x}^2`, `${x} * ${y}`) are only valid in `m.objective(...)
|
|
194
|
+
- **No quadratic constraints or MIQP**: Quadratic terms (`${x}^2`, `${x} * ${y}`) are only valid in `m.objective(...)` (using them in `m.constraint(...)` throws `"Quadratic constraints are not supported"`), and built-in HiGHS requires Convex QP models to contain only continuous variables (`m.continuous`).
|
|
195
195
|
- **Do not confuse `LinExpr` and `Constraint`**: `m.objective(maximize(...))` requires a `LinExpr`, `QuadExpr`, `Var`, or `number` (never a `Constraint`). `m.constraint(...)` requires a `Constraint` (with `<=`, `>=`, `==`, or `=`) or `BoolExpr` (never a bare `LinExpr`).
|
|
196
196
|
- **Do not mutate during async solve/check**: Modifying variables, bounds, constraints, or the objective while `await m.solve()` or `await m.check()` is pending invalidates the in-flight run and rejects the promise.
|
|
197
197
|
- **Do not use retired aliases**: Always use `expr` (not `c`), `m.constraint(...)` (not `m.constrain` or `m.add`), `m.objective(maximize(...))` (not `m.maximize` or `m.setObjective`), `await m.solve()` (not `m.optimize`), `.le()` / `.ge()` / `.eq()` (not `.lessThanOrEqual()`), `.value` / `m.getValues(...)` (not `.getValue()`), and `m.variables` / `m.constraints` (not `m.vars` / `m.constrs`).
|
|
198
|
+
- **Practical OR formulation guardrails**:
|
|
199
|
+
- **Prefer inequalities (`>=` / `<=`) over `==`** for demand coverage and capacity limits when costs are non-negative; reserve `==` for flow conservation or normalization identities.
|
|
200
|
+
- **Provide finite `lb` and `ub` bounds** on variables inside `m.indicator(...)` and omit `M` so WaSHI automatically derives the tightest valid Big-M instead of a loose `1e6` fallback.
|
|
201
|
+
- **Use soft constraints (non-negative slack variables)** with tiered objective penalties for non-rigid business targets (preferred staffing, safety stock, day-off requests) so minor data contention produces a prioritized trade-off rather than `"Infeasible"`.
|