@ohtaman/washi 0.4.0 → 0.5.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 +100 -107
- package/README.md +98 -105
- package/README.zh-CN.md +101 -108
- package/dist/browser/highs-worker.js +21 -3
- package/dist/browser/loader-CtaDHef_.js +273 -0
- package/dist/browser/solvers/glpk.js +433 -286
- package/dist/browser/solvers/glpk.min.js +1 -1
- package/dist/browser/solvers/z3.js +1002 -981
- package/dist/browser/solvers/z3.min.js +2 -2
- package/dist/browser/washi.js +2129 -676
- package/dist/browser/washi.min.js +4 -4
- package/dist/lib/highs-worker.js +21 -3
- package/dist/lib/loader-DmNC_UNk.js +279 -0
- package/dist/lib/registry-BEfvpZW3.js +951 -0
- package/dist/lib/solvers/glpk.js +201 -90
- package/dist/lib/solvers/z3.js +399 -259
- package/dist/lib/washi.js +1627 -988
- package/dist/types/index.d.ts +4 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modeler/big-m.d.ts +75 -0
- package/dist/types/modeler/big-m.d.ts.map +1 -0
- package/dist/types/modeler/boolean-expr.d.ts +103 -14
- package/dist/types/modeler/boolean-expr.d.ts.map +1 -1
- package/dist/types/modeler/constraint.d.ts +36 -9
- package/dist/types/modeler/constraint.d.ts.map +1 -1
- package/dist/types/modeler/expression.d.ts +113 -28
- package/dist/types/modeler/expression.d.ts.map +1 -1
- package/dist/types/modeler/index.d.ts +10 -6
- package/dist/types/modeler/index.d.ts.map +1 -1
- package/dist/types/modeler/lp-writer.d.ts +27 -2
- package/dist/types/modeler/lp-writer.d.ts.map +1 -1
- package/dist/types/modeler/model.d.ts +478 -131
- package/dist/types/modeler/model.d.ts.map +1 -1
- package/dist/types/modeler/objective.d.ts +59 -0
- package/dist/types/modeler/objective.d.ts.map +1 -0
- package/dist/types/modeler/parser.d.ts +34 -10
- package/dist/types/modeler/parser.d.ts.map +1 -1
- package/dist/types/modeler/quad-expr.d.ts +26 -7
- package/dist/types/modeler/quad-expr.d.ts.map +1 -1
- package/dist/types/modeler/solution-validator.d.ts +93 -0
- package/dist/types/modeler/solution-validator.d.ts.map +1 -0
- package/dist/types/modeler/solvers/glpk/solver.d.ts +26 -2
- package/dist/types/modeler/solvers/glpk/solver.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/loader.d.ts +36 -11
- package/dist/types/modeler/solvers/highs/loader.d.ts.map +1 -1
- package/dist/types/modeler/solvers/highs/solver.d.ts +11 -4
- 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/mock.d.ts +14 -5
- package/dist/types/modeler/solvers/mock.d.ts.map +1 -1
- package/dist/types/modeler/solvers/types.d.ts +71 -11
- package/dist/types/modeler/solvers/types.d.ts.map +1 -1
- package/dist/types/modeler/solvers/z3/loader.d.ts +2 -3
- package/dist/types/modeler/solvers/z3/loader.d.ts.map +1 -1
- package/dist/types/modeler/solvers/z3/solver.d.ts +15 -5
- package/dist/types/modeler/solvers/z3/solver.d.ts.map +1 -1
- package/dist/types/modeler/types.d.ts +59 -1
- package/dist/types/modeler/types.d.ts.map +1 -1
- package/dist/types/modeler/validation.d.ts +56 -0
- package/dist/types/modeler/validation.d.ts.map +1 -0
- package/dist/types/modeler/variable.d.ts +48 -14
- package/dist/types/modeler/variable.d.ts.map +1 -1
- package/docs/examples/diet-sensitivity.md +90 -0
- package/docs/examples/ecommerce-coupons.md +106 -0
- package/docs/examples/index.md +53 -0
- package/docs/examples/knapsack.md +60 -0
- package/docs/examples/portfolio-qp.md +83 -0
- package/docs/examples/production.md +51 -0
- package/docs/examples/shift-scheduling.md +175 -0
- package/docs/examples/smt-security.md +74 -0
- package/docs/examples/transportation.md +90 -0
- package/docs/examples/unsat-core.md +64 -0
- package/docs/getting-started/ai-agents.md +267 -0
- package/docs/getting-started/cross-origin.md +87 -0
- package/docs/getting-started/index.md +116 -0
- package/docs/getting-started/runtimes.md +227 -0
- package/docs/guide/constraints.md +177 -0
- package/docs/guide/expressions.md +204 -0
- package/docs/guide/objectives.md +170 -0
- package/docs/guide/unsat-core.md +147 -0
- package/docs/guide/variables.md +188 -0
- package/docs/ja/getting-started/ai-agents.md +266 -0
- package/docs/solvers/custom-solver.md +525 -0
- package/docs/solvers/glpk.md +66 -0
- package/docs/solvers/highs.md +93 -0
- package/docs/solvers/index.md +42 -0
- package/docs/solvers/z3.md +78 -0
- package/docs/zh/getting-started/ai-agents.md +266 -0
- package/llms-full.txt +3249 -0
- package/llms.txt +197 -0
- package/package.json +18 -5
- package/skills/washi/SKILL.md +197 -0
- package/dist/browser/loader-CVt4CloI.js +0 -58
- package/dist/lib/async-mutex-Duo4jwzn.js +0 -195
- package/dist/lib/constraint-BRuB3ooC.js +0 -90
- package/dist/lib/loader-Dti0v9yC.js +0 -50
- package/dist/lib/registry-DksqCSjI.js +0 -32
|
@@ -1,18 +1,66 @@
|
|
|
1
|
-
import type { SolverStatus } from "../types.js";
|
|
2
|
-
import type {
|
|
1
|
+
import type { OptimizationSense, SolverStatus, TerminationStatus, SolveProgressEvent } from "../types.js";
|
|
2
|
+
import type { Var } from "../variable.js";
|
|
3
|
+
import type { LinExpr } from "../expression.js";
|
|
4
|
+
import type { QuadExpr } from "../quad-expr.js";
|
|
5
|
+
import type { Constraint } from "../constraint.js";
|
|
6
|
+
import type { BoolVar, LogicElement } from "../boolean-expr.js";
|
|
7
|
+
/**
|
|
8
|
+
* Named logical constraint entry in a model snapshot.
|
|
9
|
+
*/
|
|
10
|
+
export interface LogicalConstraintItem {
|
|
11
|
+
name: string;
|
|
12
|
+
expr: LogicElement;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Typed model snapshot passed to `Solver.check()` (objective-free satisfiability / feasibility).
|
|
16
|
+
*
|
|
17
|
+
* Each entity in `variables`, `boolVars`, and `constraints` carries its own model-unique
|
|
18
|
+
* `.name` (and numeric `.id`), while `logicalConstraints` entries carry their `.name` and
|
|
19
|
+
* AST `.expr`. Adapters should key returned `values`, `duals`, `reducedCosts`, `slacks`,
|
|
20
|
+
* and `unsatCore` by these canonical model names (`v.name`, `bv.name`, `c.name`, `lc.name`),
|
|
21
|
+
* keeping any backend-specific identifier sanitization internal to the adapter.
|
|
22
|
+
*/
|
|
23
|
+
export interface CheckModelData {
|
|
24
|
+
name?: string;
|
|
25
|
+
variables: Var[];
|
|
26
|
+
boolVars?: BoolVar[];
|
|
27
|
+
constraints: Constraint[];
|
|
28
|
+
logicalConstraints?: LogicalConstraintItem[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Typed model snapshot passed to `Solver.solve()` (optimization with an objective).
|
|
32
|
+
*/
|
|
33
|
+
export interface SolveModelData extends CheckModelData {
|
|
34
|
+
sense: OptimizationSense;
|
|
35
|
+
objective: LinExpr | QuadExpr;
|
|
36
|
+
}
|
|
3
37
|
/**
|
|
4
38
|
* Normalized solution result returned by any solver adapter
|
|
5
39
|
*/
|
|
6
40
|
export interface SolverResult {
|
|
7
41
|
status: SolverStatus;
|
|
42
|
+
/** Exact termination reason independent of whether a feasible incumbent is available */
|
|
43
|
+
terminationStatus?: TerminationStatus;
|
|
44
|
+
/** Whether a feasible primal solution / incumbent is available */
|
|
45
|
+
hasPrimalSolution?: boolean;
|
|
8
46
|
objectiveValue: number | null;
|
|
9
|
-
/**
|
|
47
|
+
/** Best proven dual/objective bound when provided by the solver */
|
|
48
|
+
objectiveBound?: number;
|
|
49
|
+
/** Relative MIP optimality gap when provided by the solver */
|
|
50
|
+
relGap?: number;
|
|
51
|
+
/** Alias for relGap: relative MIP optimality gap when provided by the solver */
|
|
52
|
+
mipGap?: number;
|
|
53
|
+
/** Absolute MIP optimality gap |objectiveValue - objectiveBound| when provided by the solver */
|
|
54
|
+
absGap?: number;
|
|
55
|
+
/** Variable primal values (keyed by canonical variable name) */
|
|
10
56
|
values: Record<string, number>;
|
|
11
|
-
/**
|
|
57
|
+
/** Boolean variable assignments (optional, keyed by canonical BoolVar name) */
|
|
58
|
+
boolValues?: Record<string, boolean>;
|
|
59
|
+
/** Variable reduced costs (optional, keyed by canonical variable name) */
|
|
12
60
|
reducedCosts?: Record<string, number>;
|
|
13
|
-
/** Constraint dual values (optional) */
|
|
61
|
+
/** Constraint dual values (optional, keyed by canonical constraint name) */
|
|
14
62
|
duals?: Record<string, number>;
|
|
15
|
-
/** Constraint slacks (optional) */
|
|
63
|
+
/** Constraint slacks (optional, keyed by canonical constraint name) */
|
|
16
64
|
slacks?: Record<string, number>;
|
|
17
65
|
/** Solution time in seconds */
|
|
18
66
|
runTime?: number;
|
|
@@ -30,12 +78,20 @@ export interface SolverOptions {
|
|
|
30
78
|
presolve?: "on" | "off" | "choose";
|
|
31
79
|
/** Relative MIP gap tolerance (e.g. 0.01 for 1%) */
|
|
32
80
|
mipGap?: number;
|
|
81
|
+
/** Relative MIP gap tolerance alias */
|
|
82
|
+
relGap?: number;
|
|
83
|
+
/** Absolute MIP gap tolerance */
|
|
84
|
+
absGap?: number;
|
|
33
85
|
/** Number of parallel threads */
|
|
34
86
|
threads?: number;
|
|
35
87
|
/** Enable verbose solver logging */
|
|
36
88
|
verbose?: boolean;
|
|
37
89
|
/** Use Web Worker for non-blocking browser execution */
|
|
38
90
|
useWorker?: boolean;
|
|
91
|
+
/** AbortSignal to cancel an in-flight solve */
|
|
92
|
+
signal?: AbortSignal;
|
|
93
|
+
/** Callback invoked with real solver progress metrics when available */
|
|
94
|
+
onProgress?: (progress: SolveProgressEvent) => void;
|
|
39
95
|
/** Additional solver-specific options */
|
|
40
96
|
[key: string]: any;
|
|
41
97
|
}
|
|
@@ -53,18 +109,22 @@ export interface SolverCapabilities {
|
|
|
53
109
|
supportsSMT?: boolean;
|
|
54
110
|
/** Supports extracting an unsatisfiable core (conflicting constraint subset; minimality is not guaranteed) */
|
|
55
111
|
supportsUnsatCore?: boolean;
|
|
112
|
+
/** Supports primal initial values (MIP starts / warm-start hints) */
|
|
113
|
+
supportsWarmStart?: boolean;
|
|
56
114
|
}
|
|
57
115
|
export interface SolverCheckResult {
|
|
58
116
|
status: "Sat" | "Unsat" | "Unknown";
|
|
59
117
|
values: Record<string, number | boolean>;
|
|
60
|
-
unsatCore?: string[];
|
|
118
|
+
unsatCore?: readonly string[];
|
|
119
|
+
/** Alias for unsatCore: subset of conflicting constraints causing infeasibility */
|
|
120
|
+
conflicts?: readonly string[];
|
|
61
121
|
runTime?: number;
|
|
62
122
|
logs?: string[];
|
|
63
123
|
raw?: any;
|
|
64
124
|
}
|
|
65
125
|
/**
|
|
66
126
|
* Universal Solver interface.
|
|
67
|
-
* Any optimization engine (HiGHS WASM, GLPK, Gurobi Remote, CBC, SCIP, custom JS)
|
|
127
|
+
* Any optimization engine (HiGHS WASM, GLPK, Z3, Gurobi Remote, CBC, SCIP, custom JS)
|
|
68
128
|
* implements this interface to be used interchangeably with Model.
|
|
69
129
|
*/
|
|
70
130
|
export interface Solver {
|
|
@@ -77,10 +137,10 @@ export interface Solver {
|
|
|
77
137
|
/**
|
|
78
138
|
* Solve the given mathematical programming model data
|
|
79
139
|
*/
|
|
80
|
-
solve(modelData:
|
|
140
|
+
solve(modelData: SolveModelData, options?: SolverOptions): Promise<SolverResult>;
|
|
81
141
|
/**
|
|
82
|
-
* Check satisfiability of the model and logical constraints (optional)
|
|
142
|
+
* Check satisfiability of the model and logical constraints without an objective (optional)
|
|
83
143
|
*/
|
|
84
|
-
check?(modelData:
|
|
144
|
+
check?(modelData: CheckModelData, options?: SolverOptions): Promise<SolverCheckResult>;
|
|
85
145
|
}
|
|
86
146
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modeler/solvers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modeler/solvers/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
type Z3Instance = any;
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function notifyZ3WorkerError(err: any): void;
|
|
2
|
+
export declare function registerZ3ErrorHandler(handler: (err: Error) => void, instance?: Z3Instance): () => void;
|
|
3
|
+
export declare function notifyZ3WorkerError(err: unknown): void;
|
|
5
4
|
/**
|
|
6
5
|
* Configure explicit URLs for Z3 assets (z3-built.js and z3-built.wasm).
|
|
7
6
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/modeler/solvers/z3/loader.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/modeler/solvers/z3/loader.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG,GAAG,CAAC;AAkEtB,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,IAAI,CASvG;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAEtD;AAkED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAI1F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA4BnD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiBjJ;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAuFpE;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAwG5H;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBnE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { Solver, SolverCapabilities, SolverOptions, SolverResult, SolverCheckResult } from "../types.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import type { CheckModelData, SolveModelData, Solver, SolverCapabilities, SolverOptions, SolverResult, SolverCheckResult } from "../types.js";
|
|
2
|
+
import { type LpExportResult, type LpModelData } from "../../lp-writer.js";
|
|
3
|
+
import { resetZ3LoaderCache, killZ3Threads, notifyZ3WorkerError } from "./loader.js";
|
|
4
|
+
export { resetZ3LoaderCache, killZ3Threads, notifyZ3WorkerError };
|
|
4
5
|
/**
|
|
5
6
|
* Z3 SMT / SAT / MIP Solver Adapter
|
|
6
7
|
*
|
|
@@ -9,6 +10,12 @@ export { resetZ3LoaderCache, killZ3Threads, unlockAllZ3Semaphores, notifyZ3Worke
|
|
|
9
10
|
* - Feasibility checking via check()
|
|
10
11
|
* - Unsatisfiable core extraction (unsatCore) for conflict diagnosis
|
|
11
12
|
* - Mixed-Integer Programming (MIP) optimization via Z3 Optimize
|
|
13
|
+
*
|
|
14
|
+
* Solution metrics provided by Z3:
|
|
15
|
+
* - `status` and `terminationStatus`: `"Optimal" | "Infeasible" | "Error"`
|
|
16
|
+
* - `hasPrimalSolution`: `true` when Z3 returns `"sat"` (`status === "Optimal"`), `false` otherwise.
|
|
17
|
+
* - `objectiveValue`: Primal objective value when `hasPrimalSolution` is `true`, otherwise `null`.
|
|
18
|
+
* - `objectiveBound`, `relGap` (`mipGap`), `absGap`: Z3 Optimize is an SMT optimization engine and does not expose branch-and-bound MIP dual bounds or relative/absolute MIP gaps, so these fields are intentionally left `undefined` rather than returning invented defaults.
|
|
12
19
|
*/
|
|
13
20
|
export declare class Z3Solver implements Solver {
|
|
14
21
|
readonly name = "z3";
|
|
@@ -17,15 +24,18 @@ export declare class Z3Solver implements Solver {
|
|
|
17
24
|
* Helper to build AST translations for a given Z3 Context
|
|
18
25
|
*/
|
|
19
26
|
private createContextTranslator;
|
|
27
|
+
private addVariableBounds;
|
|
28
|
+
private runZ3CheckWithErrorGuard;
|
|
20
29
|
/**
|
|
21
30
|
* Check feasibility & propositional satisfaction without an objective function.
|
|
22
31
|
* Tracks constraints to return an unsatCore if infeasible.
|
|
23
32
|
*/
|
|
24
|
-
check(modelData:
|
|
33
|
+
check(modelData: CheckModelData, options?: SolverOptions): Promise<SolverCheckResult>;
|
|
25
34
|
/**
|
|
26
35
|
* Solve optimization problem (MIP) or feasibility problem
|
|
27
36
|
*/
|
|
28
|
-
solve(modelData:
|
|
37
|
+
solve(modelData: SolveModelData, options?: SolverOptions): Promise<SolverResult>;
|
|
38
|
+
solve(modelData: LpModelData, lpResult: LpExportResult, options?: SolverOptions): Promise<SolverResult>;
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
41
|
* Register Z3 solver into global solver registry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solver.d.ts","sourceRoot":"","sources":["../../../../../src/modeler/solvers/z3/solver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,MAAM,EACN,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,iBAAiB,EAClB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"solver.d.ts","sourceRoot":"","sources":["../../../../../src/modeler/solvers/z3/solver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAU,kBAAkB,EAAE,aAAa,EAA0B,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAErH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC;AAWlE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAS,YAAW,MAAM;IACrC,QAAQ,CAAC,IAAI,QAAQ;IACrB,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAMvC;IAEF;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgO/B,OAAO,CAAC,iBAAiB;YAqBX,wBAAwB;IAgBtC;;;OAGG;IACG,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2G9F;IAED;;OAEG;IACG,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACjF,KAAK,CACT,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC,CAAC;CAkR1B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
|
@@ -4,11 +4,37 @@
|
|
|
4
4
|
export type VarType = "Continuous" | "Integer" | "Binary" | "continuous" | "integer" | "binary" | "cont" | "int" | "bin";
|
|
5
5
|
export type OptimizationSense = "Minimize" | "Maximize" | "minimize" | "maximize";
|
|
6
6
|
/**
|
|
7
|
-
* Normalizes user-facing optimization sense to internal canonical form ("Maximize" | "Minimize")
|
|
7
|
+
* Normalizes user-facing optimization sense to internal canonical form ("Maximize" | "Minimize").
|
|
8
|
+
* Throws a descriptive error if an invalid sense string is provided at runtime.
|
|
8
9
|
*/
|
|
9
10
|
export declare function normalizeSense(sense?: OptimizationSense): "Maximize" | "Minimize";
|
|
10
11
|
export type ComparisonSense = "<=" | ">=" | "==";
|
|
11
12
|
export type SolverStatus = "Optimal" | "Feasible" | "Infeasible" | "Unbounded" | "TimeLimit" | "IterationLimit" | "Error" | "NotSolved" | "Sat" | "Unsat" | "Unknown";
|
|
13
|
+
export type TerminationStatus = "Optimal" | "Feasible" | "Infeasible" | "Unbounded" | "InfeasibleOrUnbounded" | "TimeLimit" | "IterationLimit" | "SolutionLimit" | "MemoryLimit" | "ObjectiveBound" | "ObjectiveTarget" | "Interrupted" | "Error" | "NotSolved" | "Sat" | "Unsat" | "Unknown";
|
|
14
|
+
export interface SolveProgressEvent {
|
|
15
|
+
/** Elapsed solver time in seconds */
|
|
16
|
+
elapsedTime: number;
|
|
17
|
+
/** Alias for elapsedTime: elapsed solver time in seconds */
|
|
18
|
+
elapsedSeconds?: number;
|
|
19
|
+
/** Current solver phase when known */
|
|
20
|
+
phase?: "simplex" | "ipm" | "mip";
|
|
21
|
+
/** Best feasible incumbent objective value when available */
|
|
22
|
+
objectiveValue?: number;
|
|
23
|
+
/** Best proven dual / objective bound when available */
|
|
24
|
+
objectiveBound?: number;
|
|
25
|
+
/** Relative MIP optimality gap when available */
|
|
26
|
+
relGap?: number;
|
|
27
|
+
/** Alias for relGap: relative MIP optimality gap when available */
|
|
28
|
+
mipGap?: number;
|
|
29
|
+
/** Absolute MIP optimality gap |objectiveValue - objectiveBound| when available */
|
|
30
|
+
absGap?: number;
|
|
31
|
+
/** Explored MIP branch-and-bound node count when available */
|
|
32
|
+
nodes?: number;
|
|
33
|
+
/** Solver iteration count (simplex, IPM, or MIP LP iterations) when available */
|
|
34
|
+
iterations?: number;
|
|
35
|
+
/** Optional raw progress message from the solver */
|
|
36
|
+
message?: string;
|
|
37
|
+
}
|
|
12
38
|
export interface SolveOptions {
|
|
13
39
|
timeLimit?: number;
|
|
14
40
|
outputFlag?: boolean;
|
|
@@ -17,11 +43,35 @@ export interface SolveOptions {
|
|
|
17
43
|
relGap?: number;
|
|
18
44
|
absGap?: number;
|
|
19
45
|
wasmUrl?: string;
|
|
46
|
+
/**
|
|
47
|
+
* AbortSignal to cancel a solve:
|
|
48
|
+
* - Pre-solve cancellation (`signal.aborted` before execution starts) is supported by all solvers.
|
|
49
|
+
* - Preemptive mid-solve cancellation is supported in browser HiGHS via Web Worker termination
|
|
50
|
+
* (and cancels queued Worker requests before they are dispatched).
|
|
51
|
+
* - Main-thread (Node.js) HiGHS supports cooperative mid-solve cancellation when `abort()` is
|
|
52
|
+
* triggered synchronously inside an `onProgress` callback at a solver interrupt checkpoint.
|
|
53
|
+
* - Single-threaded WASM solvers without interrupt hooks (GLPK, Z3) check `signal` before execution starts.
|
|
54
|
+
*/
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
/** Callback invoked with real solver progress metrics when available */
|
|
57
|
+
onProgress?: (progress: SolveProgressEvent) => void;
|
|
20
58
|
[key: string]: any;
|
|
21
59
|
}
|
|
22
60
|
export interface SolverSolution {
|
|
23
61
|
status: SolverStatus;
|
|
62
|
+
/** Exact termination reason independent of whether a feasible incumbent is available */
|
|
63
|
+
terminationStatus: TerminationStatus;
|
|
64
|
+
/** Whether a feasible primal solution / incumbent is available */
|
|
65
|
+
hasPrimalSolution: boolean;
|
|
24
66
|
objectiveValue: number | null;
|
|
67
|
+
/** Best proven dual/objective bound when provided by the solver */
|
|
68
|
+
objectiveBound?: number;
|
|
69
|
+
/** Relative MIP optimality gap when provided by the solver */
|
|
70
|
+
relGap?: number;
|
|
71
|
+
/** Alias for relGap: relative MIP optimality gap when provided by the solver */
|
|
72
|
+
mipGap?: number;
|
|
73
|
+
/** Absolute MIP optimality gap |objectiveValue - objectiveBound| when provided by the solver */
|
|
74
|
+
absGap?: number;
|
|
25
75
|
values: Record<string, number>;
|
|
26
76
|
duals: Record<string, number>;
|
|
27
77
|
reducedCosts: Record<string, number>;
|
|
@@ -29,4 +79,12 @@ export interface SolverSolution {
|
|
|
29
79
|
runTime: number;
|
|
30
80
|
raw?: any;
|
|
31
81
|
}
|
|
82
|
+
export interface CheckResult {
|
|
83
|
+
status: "Sat" | "Unsat" | "Unknown";
|
|
84
|
+
values: Record<string, number | boolean>;
|
|
85
|
+
unsatCore?: readonly string[];
|
|
86
|
+
/** Alias for unsatCore: subset of conflicting constraints causing infeasibility */
|
|
87
|
+
conflicts?: readonly string[];
|
|
88
|
+
runTime?: number;
|
|
89
|
+
}
|
|
32
90
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modeler/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,OAAO,GACf,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,MAAM,GACN,KAAK,GACL,KAAK,CAAC;AAEV,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modeler/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Model } from "./model.js";
|
|
2
|
+
import { Var } from "./variable.js";
|
|
3
|
+
import { BoolVar, type LogicElement } from "./boolean-expr.js";
|
|
4
|
+
import { Constraint } from "./constraint.js";
|
|
5
|
+
import { LinExpr } from "./expression.js";
|
|
6
|
+
import { QuadExpr } from "./quad-expr.js";
|
|
7
|
+
/**
|
|
8
|
+
* Recursively attaches ownerModel mutation tracking to any Constraint nodes embedded in a logical expression.
|
|
9
|
+
*/
|
|
10
|
+
export declare function attachLogicElementOwnership(elem: LogicElement, model: Model, undoActions?: (() => void)[]): void;
|
|
11
|
+
/**
|
|
12
|
+
* Associates a variable instance with its owning model and rejects cross-model sharing.
|
|
13
|
+
*/
|
|
14
|
+
export declare function claimVarOwnership(v: Var, model: Model): void;
|
|
15
|
+
/**
|
|
16
|
+
* Associates a constraint instance with its owning model and rejects reusing or cross-model sharing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function claimConstraintOwnership(c: Constraint, model: Model): Model | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Releases variable ownership when rolling back a failed batch operation.
|
|
21
|
+
*/
|
|
22
|
+
export declare function releaseVarOwnership(v: Var, model: Model): void;
|
|
23
|
+
/**
|
|
24
|
+
* Releases constraint ownership when rolling back a failed batch operation.
|
|
25
|
+
*/
|
|
26
|
+
export declare function releaseConstraintOwnership(c: Constraint, model: Model, previousOwner?: Model): void;
|
|
27
|
+
/**
|
|
28
|
+
* Numerical tolerance used when validating variable initial values against bounds and integrality.
|
|
29
|
+
*/
|
|
30
|
+
export declare const INITIAL_VALUE_TOLERANCE = 0.000001;
|
|
31
|
+
/**
|
|
32
|
+
* Validates lower and upper bounds (and optional primal initialValue) of a single variable.
|
|
33
|
+
*/
|
|
34
|
+
export declare function validateVarBounds(v: Var): void;
|
|
35
|
+
/**
|
|
36
|
+
* Validates and normalizes a variable's optional primal initialValue for solver consumption.
|
|
37
|
+
* Rounds near-integer values for Integer/Binary variables and clamps near-bound values for Continuous variables.
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizeVarInitialValue(v: Var): number | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Validates objective expression constants, coefficients, and variable ownership.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateObjectiveExpr(expr: LinExpr | QuadExpr, modelName: string, isOwnedVar: (v: Var) => boolean): void;
|
|
44
|
+
/**
|
|
45
|
+
* Validates a linear constraint's RHS, LHS constant, coefficients, and variable ownership.
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateLinearConstraint(c: Constraint, modelName: string, isOwnedVar: (v: Var) => boolean, constrName?: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Validates a logical constraint element recursively.
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateLogicElement(elem: LogicElement, lcName: string, modelName: string, isOwnedVar: (v: Var) => boolean, isOwnedBoolVar: (bv: BoolVar) => boolean, ownerModel?: Model): void;
|
|
52
|
+
/**
|
|
53
|
+
* Validates the structural and numerical integrity of an optimization model.
|
|
54
|
+
*/
|
|
55
|
+
export declare function validateModelIntegrity(model: Model): void;
|
|
56
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/modeler/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM1C;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,KAAK,EACZ,WAAW,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,GAC3B,IAAI,CAuBN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAQ5D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAkBvF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAI9D;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,CAAC,EAAE,UAAU,EACb,KAAK,EAAE,KAAK,EACZ,aAAa,CAAC,EAAE,KAAK,GACpB,IAAI,CAWN;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,WAAO,CAAC;AAE5C;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAwD9C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAWnE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,GAAG,QAAQ,EACxB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,GAC9B,IAAI,CAuDN;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,UAAU,EACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,EAC/B,UAAU,SAAS,GAClB,IAAI,CAuBN;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,EAC/B,cAAc,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,EACxC,UAAU,CAAC,EAAE,KAAK,GACjB,IAAI,CA2CN;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAiGzD"}
|
|
@@ -8,46 +8,80 @@ export interface VarOptions {
|
|
|
8
8
|
type?: VarType;
|
|
9
9
|
lb?: number;
|
|
10
10
|
ub?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Optional finite primal initial value (MIP start / warm-start hint), distinct from solved `Var.value`.
|
|
13
|
+
* Validated within tolerance `1e-6` against `[lb, ub]` and integer/binary domains.
|
|
14
|
+
* Supported by HiGHS (`supportsWarmStart: true`); throws on solvers without warm-start support (GLPK, Z3).
|
|
15
|
+
*/
|
|
16
|
+
initialValue?: number;
|
|
11
17
|
}
|
|
12
18
|
/**
|
|
13
|
-
* Represents a decision variable in an optimization
|
|
19
|
+
* Represents a numeric decision variable (`"Continuous"`, `"Integer"`, or `"Binary"`) in an optimization model.
|
|
20
|
+
* Typically created and registered via `m.continuous(...)`, `m.integer(...)`, or `m.binary(...)`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const m = new Model("VarExample");
|
|
25
|
+
* const x = m.continuous("x", { lb: 0, ub: 100 });
|
|
26
|
+
* const y = m.integer("y", { lb: 0, ub: 10, initialValue: 5 });
|
|
27
|
+
* m.objective(maximize(x.mul(2).add(y.mul(5))));
|
|
28
|
+
* m.constraint(x.add(y).le(50));
|
|
29
|
+
* ```
|
|
14
30
|
*/
|
|
15
31
|
export declare class Var {
|
|
16
32
|
readonly id: number;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
private _name;
|
|
34
|
+
readonly prefix: string;
|
|
35
|
+
hasExplicitName: boolean;
|
|
36
|
+
ownerModel: {
|
|
37
|
+
notifyMutation?: () => void;
|
|
38
|
+
} | null;
|
|
39
|
+
private _type;
|
|
40
|
+
private _lb;
|
|
41
|
+
private _ub;
|
|
42
|
+
private _initialValue;
|
|
21
43
|
/** Optimal primal value after solve */
|
|
22
44
|
value: number | null;
|
|
23
45
|
/** Reduced cost from dual solution */
|
|
24
46
|
reducedCost: number | null;
|
|
25
47
|
constructor(options?: VarOptions);
|
|
48
|
+
get name(): string;
|
|
49
|
+
get type(): "Continuous" | "Integer" | "Binary";
|
|
50
|
+
set type(val: VarType);
|
|
51
|
+
get lb(): number;
|
|
52
|
+
set lb(val: number);
|
|
53
|
+
get ub(): number;
|
|
54
|
+
set ub(val: number);
|
|
55
|
+
/**
|
|
56
|
+
* Optional finite primal initial value (MIP start / warm-start hint), distinct from solved `Var.value`.
|
|
57
|
+
* Supported by HiGHS (`supportsWarmStart: true`); throws on solvers without warm-start support (GLPK, Z3).
|
|
58
|
+
*/
|
|
59
|
+
get initialValue(): number | undefined;
|
|
60
|
+
set initialValue(val: number | undefined);
|
|
61
|
+
/** @internal Assigns a model-scoped name when registering an unnamed Var via Model.add() */
|
|
62
|
+
_assignModelName(name: string): void;
|
|
26
63
|
/** Multiply variable by a scalar coefficient or another variable/expression */
|
|
27
64
|
mul(coeff: number): LinExpr;
|
|
28
65
|
mul(other: Var): QuadExpr;
|
|
29
66
|
mul(other: LinExpr): QuadExpr;
|
|
30
67
|
mul(other: QuadExpr): QuadExpr;
|
|
31
|
-
mul(other: number | Var | LinExpr | QuadExpr): LinExpr | QuadExpr;
|
|
68
|
+
mul(other: number | Var | LinExpr | QuadExpr | Constraint): LinExpr | QuadExpr;
|
|
32
69
|
/** Add variable with another variable, linear/quadratic expression, or number */
|
|
33
70
|
add(other: QuadExpr): QuadExpr;
|
|
34
71
|
add(other: Var | LinExpr | number): LinExpr;
|
|
35
|
-
add(other: Var | LinExpr | QuadExpr | number): LinExpr | QuadExpr;
|
|
72
|
+
add(other: Var | LinExpr | QuadExpr | number | Constraint): LinExpr | QuadExpr;
|
|
36
73
|
/** Subtract another variable, linear/quadratic expression, or number from this variable */
|
|
37
74
|
sub(other: QuadExpr): QuadExpr;
|
|
38
75
|
sub(other: Var | LinExpr | number): LinExpr;
|
|
39
|
-
sub(other: Var | LinExpr | QuadExpr | number): LinExpr | QuadExpr;
|
|
76
|
+
sub(other: Var | LinExpr | QuadExpr | number | Constraint): LinExpr | QuadExpr;
|
|
40
77
|
/** Negate this variable: -x */
|
|
41
78
|
neg(): LinExpr;
|
|
42
79
|
/** Create a less-than-or-equal constraint: this <= rhs */
|
|
43
|
-
le(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
44
|
-
lessThanOrEqual(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
80
|
+
le(rhs: number | Var | LinExpr | QuadExpr | Constraint, name?: string): Constraint;
|
|
45
81
|
/** Create a greater-than-or-equal constraint: this >= rhs */
|
|
46
|
-
ge(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
47
|
-
greaterThanOrEqual(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
82
|
+
ge(rhs: number | Var | LinExpr | QuadExpr | Constraint, name?: string): Constraint;
|
|
48
83
|
/** Create an equality constraint: this == rhs */
|
|
49
|
-
eq(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
50
|
-
equalTo(rhs: number | Var | LinExpr, name?: string): Constraint;
|
|
84
|
+
eq(rhs: number | Var | LinExpr | QuadExpr | Constraint, name?: string): Constraint;
|
|
51
85
|
toString(): string;
|
|
52
86
|
}
|
|
53
87
|
//# sourceMappingURL=variable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"variable.d.ts","sourceRoot":"","sources":["../../../src/modeler/variable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"variable.d.ts","sourceRoot":"","sources":["../../../src/modeler/variable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK1C,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAeD;;;;;;;;;;;;GAYG;AACH,qBAAa,GAAG;IACd,SAAgB,EAAE,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,KAAK,CAAS;IACtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAQ;IACjE,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,aAAa,CAAqB;IAE1C,uCAAuC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,sCAAsC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzC,YAAY,OAAO,GAAE,UAAe,EA2BnC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,IAAI,YAAY,GAAG,SAAS,GAAG,QAAQ,CAE9C;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,OAAO,EAMpB;IAED,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAKjB;IAED,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAKjB;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAED,IAAI,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAMvC;IAED,4FAA4F;IAC5F,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,+EAA+E;IAC/E,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,QAAQ,CAAC;IAC1B,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IAQ/E,iFAAiF;IACjF,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IAQ/E,2FAA2F;IAC3F,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IAQ/E,+BAA+B;IAC/B,GAAG,IAAI,OAAO,CAEb;IAED,0DAA0D;IAC1D,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAEjF;IAED,6DAA6D;IAC7D,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAEjF;IAED,iDAAiD;IACjD,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAEjF;IAED,QAAQ,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Diet Problem & Sensitivity Analysis (LP Duals & Slacks)
|
|
2
|
+
|
|
3
|
+
| Problem Class | Solver | Key APIs | Links |
|
|
4
|
+
| :--- | :--- | :--- | :--- |
|
|
5
|
+
| Linear Programming (LP) | HiGHS (default) | `m.continuous()`, `m.constraint()`, `expr`, `minimize`, `dot` | <ul><li><a href="https://ohtaman.github.io/washi/demo/?preset=diet_sensitivity">Open in Playground</a></li><li><a href="https://github.com/ohtaman/washi/blob/main/examples/node/10-diet-sensitivity.ts">Source Code</a></li></ul> |
|
|
6
|
+
|
|
7
|
+
When solving a Linear Programming model, the optimal variable values (`var.value`) are only half the story. In practice, decision-makers need to know:
|
|
8
|
+
|
|
9
|
+
1. **Bottlenecks (`constr.dual` — Shadow Price):** Which minimum requirements are actively driving up the total cost, and by how much per unit?
|
|
10
|
+
2. **Surpluses (`constr.slack`):** Which constraints have room to spare?
|
|
11
|
+
3. **Reduced Costs (`var.reducedCost`):** For items not selected in the optimal plan, how much cheaper would they need to become before entering the solution?
|
|
12
|
+
|
|
13
|
+
## Problem Inputs
|
|
14
|
+
|
|
15
|
+
We choose daily servings ($0 \le x_i \le 4$) among 6 food items to meet 4 daily nutritional minimums (`Calories >= 2000 kcal`, `Protein >= 105 g`, `Calcium >= 1000 mg`, `Iron >= 18 mg`) at minimum cost:
|
|
16
|
+
|
|
17
|
+
| Food Item | Cost / Serving | Calories (kcal) | Protein (g) | Calcium (mg) | Iron (mg) | Max Servings |
|
|
18
|
+
| :--- | :---: | :---: | :---: | :---: | :---: | :---: |
|
|
19
|
+
| **Oats** | $0.60 | 150 | 5 | 20 | 1.8 | 4.0 |
|
|
20
|
+
| **Chicken** | $2.40 | 220 | 32 | 15 | 1.2 | 4.0 |
|
|
21
|
+
| **Eggs** | $0.80 | 140 | 12 | 50 | 1.7 | 4.0 |
|
|
22
|
+
| **Milk** | $0.90 | 120 | 8 | 280 | 0.1 | 4.0 |
|
|
23
|
+
| **Spinach** | $1.50 | 40 | 4 | 120 | 3.5 | 4.0 |
|
|
24
|
+
| **Salmon** | $3.60 | 200 | 25 | 20 | 0.8 | 4.0 |
|
|
25
|
+
|
|
26
|
+
## Implementation in WaSHI
|
|
27
|
+
|
|
28
|
+
<CodeRunner preset="diet_sensitivity">
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { Model, minimize, dot, expr } from "@ohtaman/washi";
|
|
32
|
+
|
|
33
|
+
const foods = [
|
|
34
|
+
{ name: "Oats", cost: 0.60, calories: 150, protein: 5, calcium: 20, iron: 1.8 },
|
|
35
|
+
{ name: "Chicken", cost: 2.40, calories: 220, protein: 32, calcium: 15, iron: 1.2 },
|
|
36
|
+
{ name: "Eggs", cost: 0.80, calories: 140, protein: 12, calcium: 50, iron: 1.7 },
|
|
37
|
+
{ name: "Milk", cost: 0.90, calories: 120, protein: 8, calcium: 280, iron: 0.1 },
|
|
38
|
+
{ name: "Spinach", cost: 1.50, calories: 40, protein: 4, calcium: 120, iron: 3.5 },
|
|
39
|
+
{ name: "Salmon", cost: 3.60, calories: 200, protein: 25, calcium: 20, iron: 0.8 },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
async function runDietSensitivity() {
|
|
43
|
+
const m = new Model("DietSensitivity");
|
|
44
|
+
|
|
45
|
+
// Continuous servings per day (0 to 4 servings max per food)
|
|
46
|
+
const srv = m.continuous(foods.map((f) => f.name), { lb: 0, ub: 4 });
|
|
47
|
+
|
|
48
|
+
const costs = Object.fromEntries(foods.map((f) => [f.name, f.cost]));
|
|
49
|
+
const cals = Object.fromEntries(foods.map((f) => [f.name, f.calories]));
|
|
50
|
+
const prots = Object.fromEntries(foods.map((f) => [f.name, f.protein]));
|
|
51
|
+
const calcs = Object.fromEntries(foods.map((f) => [f.name, f.calcium]));
|
|
52
|
+
const irons = Object.fromEntries(foods.map((f) => [f.name, f.iron]));
|
|
53
|
+
|
|
54
|
+
// Objective: Minimize total daily cost via dot product
|
|
55
|
+
m.objective(minimize(dot(costs, srv)));
|
|
56
|
+
|
|
57
|
+
// Nutritional constraints defined declaratively with expr and constraint()
|
|
58
|
+
m.constraint(expr`${dot(cals, srv)} >= 2000`, "min_calories")
|
|
59
|
+
.constraint(expr`${dot(prots, srv)} >= 105`, "min_protein")
|
|
60
|
+
.constraint(expr`${dot(calcs, srv)} >= 1000`, "min_calcium")
|
|
61
|
+
.constraint(expr`${dot(irons, srv)} >= 18`, "min_iron");
|
|
62
|
+
|
|
63
|
+
const status = await m.solve();
|
|
64
|
+
|
|
65
|
+
console.log(`Status: ${status}, Minimum Daily Cost: $${m.objectiveValue?.toFixed(2)}`);
|
|
66
|
+
console.log("--- Food Servings & Reduced Costs ---");
|
|
67
|
+
for (const f of foods) {
|
|
68
|
+
const v = srv[f.name];
|
|
69
|
+
console.log(` ${f.name.padEnd(8)}: value=${v.value?.toFixed(2)}, reducedCost=${v.reducedCost?.toFixed(4)}`);
|
|
70
|
+
}
|
|
71
|
+
console.log("--- Nutritional Constraints (Dual & Slack) ---");
|
|
72
|
+
for (const name of ["min_calories", "min_protein", "min_calcium", "min_iron"]) {
|
|
73
|
+
const c = m.getConstraintByName(name);
|
|
74
|
+
if (c) {
|
|
75
|
+
console.log(` ${c.name.padEnd(13)}: dual=$${c.dual?.toFixed(4)}, slack=${Math.abs(c.slack ?? 0).toFixed(2)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
runDietSensitivity();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
</CodeRunner>
|
|
84
|
+
|
|
85
|
+
## Interpretation of Results
|
|
86
|
+
|
|
87
|
+
- **Bottleneck constraints (`slack == 0`, `dual > 0`):** Calories (`2000 kcal`) and Iron (`18 mg`) are tight at their lower bounds. Increasing the daily Iron requirement by 1 mg increases the minimum daily diet cost by **$0.3241**.
|
|
88
|
+
- **Constraints with surplus (`slack > 0`, `dual == 0`):** Protein (`+46.46 g` surplus) and Calcium (`+483.02 mg` surplus) are already exceeded with room to spare, so their shadow prices are `$0`.
|
|
89
|
+
- **Reduced cost (`Salmon`):** Unselected `Salmon` (`0.00` servings) has a reduced cost of `+1.5125`, meaning its price per serving would need to drop by at least **$1.51** before it enters the optimal daily menu.
|
|
90
|
+
|