@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.
Files changed (97) hide show
  1. package/README.ja.md +100 -107
  2. package/README.md +98 -105
  3. package/README.zh-CN.md +101 -108
  4. package/dist/browser/highs-worker.js +21 -3
  5. package/dist/browser/loader-CtaDHef_.js +273 -0
  6. package/dist/browser/solvers/glpk.js +433 -286
  7. package/dist/browser/solvers/glpk.min.js +1 -1
  8. package/dist/browser/solvers/z3.js +1002 -981
  9. package/dist/browser/solvers/z3.min.js +2 -2
  10. package/dist/browser/washi.js +2129 -676
  11. package/dist/browser/washi.min.js +4 -4
  12. package/dist/lib/highs-worker.js +21 -3
  13. package/dist/lib/loader-DmNC_UNk.js +279 -0
  14. package/dist/lib/registry-BEfvpZW3.js +951 -0
  15. package/dist/lib/solvers/glpk.js +201 -90
  16. package/dist/lib/solvers/z3.js +399 -259
  17. package/dist/lib/washi.js +1627 -988
  18. package/dist/types/index.d.ts +4 -4
  19. package/dist/types/index.d.ts.map +1 -1
  20. package/dist/types/modeler/big-m.d.ts +75 -0
  21. package/dist/types/modeler/big-m.d.ts.map +1 -0
  22. package/dist/types/modeler/boolean-expr.d.ts +103 -14
  23. package/dist/types/modeler/boolean-expr.d.ts.map +1 -1
  24. package/dist/types/modeler/constraint.d.ts +36 -9
  25. package/dist/types/modeler/constraint.d.ts.map +1 -1
  26. package/dist/types/modeler/expression.d.ts +113 -28
  27. package/dist/types/modeler/expression.d.ts.map +1 -1
  28. package/dist/types/modeler/index.d.ts +10 -6
  29. package/dist/types/modeler/index.d.ts.map +1 -1
  30. package/dist/types/modeler/lp-writer.d.ts +27 -2
  31. package/dist/types/modeler/lp-writer.d.ts.map +1 -1
  32. package/dist/types/modeler/model.d.ts +478 -131
  33. package/dist/types/modeler/model.d.ts.map +1 -1
  34. package/dist/types/modeler/objective.d.ts +59 -0
  35. package/dist/types/modeler/objective.d.ts.map +1 -0
  36. package/dist/types/modeler/parser.d.ts +34 -10
  37. package/dist/types/modeler/parser.d.ts.map +1 -1
  38. package/dist/types/modeler/quad-expr.d.ts +26 -7
  39. package/dist/types/modeler/quad-expr.d.ts.map +1 -1
  40. package/dist/types/modeler/solution-validator.d.ts +93 -0
  41. package/dist/types/modeler/solution-validator.d.ts.map +1 -0
  42. package/dist/types/modeler/solvers/glpk/solver.d.ts +26 -2
  43. package/dist/types/modeler/solvers/glpk/solver.d.ts.map +1 -1
  44. package/dist/types/modeler/solvers/highs/loader.d.ts +36 -11
  45. package/dist/types/modeler/solvers/highs/loader.d.ts.map +1 -1
  46. package/dist/types/modeler/solvers/highs/solver.d.ts +11 -4
  47. package/dist/types/modeler/solvers/highs/solver.d.ts.map +1 -1
  48. package/dist/types/modeler/solvers/highs/worker-client.d.ts.map +1 -1
  49. package/dist/types/modeler/solvers/mock.d.ts +14 -5
  50. package/dist/types/modeler/solvers/mock.d.ts.map +1 -1
  51. package/dist/types/modeler/solvers/types.d.ts +71 -11
  52. package/dist/types/modeler/solvers/types.d.ts.map +1 -1
  53. package/dist/types/modeler/solvers/z3/loader.d.ts +2 -3
  54. package/dist/types/modeler/solvers/z3/loader.d.ts.map +1 -1
  55. package/dist/types/modeler/solvers/z3/solver.d.ts +15 -5
  56. package/dist/types/modeler/solvers/z3/solver.d.ts.map +1 -1
  57. package/dist/types/modeler/types.d.ts +59 -1
  58. package/dist/types/modeler/types.d.ts.map +1 -1
  59. package/dist/types/modeler/validation.d.ts +56 -0
  60. package/dist/types/modeler/validation.d.ts.map +1 -0
  61. package/dist/types/modeler/variable.d.ts +48 -14
  62. package/dist/types/modeler/variable.d.ts.map +1 -1
  63. package/docs/examples/diet-sensitivity.md +90 -0
  64. package/docs/examples/ecommerce-coupons.md +106 -0
  65. package/docs/examples/index.md +53 -0
  66. package/docs/examples/knapsack.md +60 -0
  67. package/docs/examples/portfolio-qp.md +83 -0
  68. package/docs/examples/production.md +51 -0
  69. package/docs/examples/shift-scheduling.md +175 -0
  70. package/docs/examples/smt-security.md +74 -0
  71. package/docs/examples/transportation.md +90 -0
  72. package/docs/examples/unsat-core.md +64 -0
  73. package/docs/getting-started/ai-agents.md +267 -0
  74. package/docs/getting-started/cross-origin.md +87 -0
  75. package/docs/getting-started/index.md +116 -0
  76. package/docs/getting-started/runtimes.md +227 -0
  77. package/docs/guide/constraints.md +177 -0
  78. package/docs/guide/expressions.md +204 -0
  79. package/docs/guide/objectives.md +170 -0
  80. package/docs/guide/unsat-core.md +147 -0
  81. package/docs/guide/variables.md +188 -0
  82. package/docs/ja/getting-started/ai-agents.md +266 -0
  83. package/docs/solvers/custom-solver.md +525 -0
  84. package/docs/solvers/glpk.md +66 -0
  85. package/docs/solvers/highs.md +93 -0
  86. package/docs/solvers/index.md +42 -0
  87. package/docs/solvers/z3.md +78 -0
  88. package/docs/zh/getting-started/ai-agents.md +266 -0
  89. package/llms-full.txt +3249 -0
  90. package/llms.txt +197 -0
  91. package/package.json +18 -5
  92. package/skills/washi/SKILL.md +197 -0
  93. package/dist/browser/loader-CVt4CloI.js +0 -58
  94. package/dist/lib/async-mutex-Duo4jwzn.js +0 -195
  95. package/dist/lib/constraint-BRuB3ooC.js +0 -90
  96. package/dist/lib/loader-Dti0v9yC.js +0 -50
  97. package/dist/lib/registry-DksqCSjI.js +0 -32
@@ -1,131 +1,330 @@
1
- import { type OptimizationSense, type SolverStatus, type SolveOptions, type SolverSolution } from "./types.js";
1
+ import { type OptimizationSense, type SolverStatus, type TerminationStatus, type SolveOptions, type SolverSolution, type CheckResult } from "./types.js";
2
+ import { type ObjectiveSpec } from "./objective.js";
2
3
  import { Var } from "./variable.js";
3
4
  import { LinExpr } from "./expression.js";
4
5
  import { QuadExpr } from "./quad-expr.js";
5
6
  import { Constraint } from "./constraint.js";
6
7
  import { BoolVar, BoolExpr } from "./boolean-expr.js";
7
8
  import { type Solver } from "./solvers/index.js";
9
+ import { type SolutionValidationOptions, type SolutionValidationReport } from "./solution-validator.js";
10
+ /**
11
+ * Valid items that can be added as a constraint to a model.
12
+ * Raw mathematical expressions (LinExpr, QuadExpr) without comparisons are strictly prohibited.
13
+ */
14
+ export type ConstraintItem = Constraint | BoolExpr | string;
8
15
  export interface ModelOptions {
16
+ /** Optional model name (default: `"OptimizationModel"`). */
9
17
  name?: string;
18
+ /** Default optimization direction (`"Minimize"` or `"Maximize"`, default: `"Minimize"`). */
10
19
  sense?: OptimizationSense;
20
+ /** Solver instance or registered solver name (`"highs"`, `"glpk"`, `"z3"`, or custom solver). */
11
21
  solver?: Solver | string;
12
22
  }
13
23
  export interface BoundsOptions {
24
+ /** Explicit name for a scalar variable, or fallback prefix for indexed variable containers. */
14
25
  name?: string;
26
+ /** Name prefix when creating unnamed scalar variables or indexed variable containers (default: `"x"`). */
15
27
  prefix?: string;
28
+ /** Lower bound (default: `0`; `-Infinity` allowed for free lower bound; `+Infinity` and `NaN` rejected). */
16
29
  lb?: number;
30
+ /** Upper bound (default: `Infinity`; `-Infinity` and `NaN` rejected; must satisfy `lb <= ub`). */
17
31
  ub?: number;
32
+ /**
33
+ * Optional finite primal initial value (MIP start / warm-start hint), distinct from solved `Var.value`.
34
+ * Validated within tolerance `1e-6` against `[lb, ub]` and integer domain.
35
+ * Supported by HiGHS (`supportsWarmStart: true`); throws on solvers without warm-start support (GLPK, Z3).
36
+ */
37
+ initialValue?: number;
38
+ [Symbol.iterator]?: never;
18
39
  }
19
- export interface IndicatorOptions {
20
- activeValue?: 0 | 1;
21
- M?: number;
40
+ export interface BinaryOptions {
41
+ /** Explicit name for a scalar variable, or fallback prefix for indexed variable containers. */
22
42
  name?: string;
43
+ /** Name prefix when creating unnamed scalar variables or indexed variable containers (default: `"x"`). */
44
+ prefix?: string;
45
+ /**
46
+ * Optional finite primal initial value (`0` or `1` within tolerance `1e-6`), distinct from solved `Var.value`.
47
+ * Supported by HiGHS (`supportsWarmStart: true`); throws on solvers without warm-start support (GLPK, Z3).
48
+ */
49
+ initialValue?: number;
50
+ [Symbol.iterator]?: never;
23
51
  }
52
+ type VarNameOptions = {
53
+ prefix?: string;
54
+ name?: string;
55
+ [Symbol.iterator]?: never;
56
+ };
57
+ import { type IndicatorOptions } from "./big-m.js";
58
+ export type { IndicatorOptions };
24
59
  /**
25
- * High-level mathematical programming model for LP, MIP, QP, and SMT,
26
- * running directly with WebAssembly solvers (HiGHS, Z3, GLPK) in browser and Node.js.
60
+ * Named propositional or SMT constraint registered on a `Model`.
27
61
  */
28
62
  export interface LogicalConstraint {
29
63
  name: string;
30
64
  expr: BoolExpr | Constraint;
31
65
  }
66
+ declare const UniqueStringTag: unique symbol;
67
+ declare global {
68
+ interface String {
69
+ readonly [UniqueStringTag]: false;
70
+ }
71
+ }
72
+ export type KeyCollection<K extends string | number> = ReadonlyArray<K> | (Iterable<K> & object & {
73
+ readonly [UniqueStringTag]?: true;
74
+ });
75
+ /**
76
+ * High-level mathematical programming and SMT model for LP, MIP, convex QP, and SAT/SMT,
77
+ * running with WebAssembly solvers (HiGHS, GLPK, Z3) in Node.js and browsers.
78
+ *
79
+ * **Solver capability notes**:
80
+ * - `"highs"` (default, built-in): Supports LP, MIP, convex QP objectives (`supportsQP: true`),
81
+ * and `initialValue` warm starts (`supportsWarmStart: true`). Also supports `m.check()` on purely
82
+ * linear models via a zero-objective feasibility fallback. Throws if `BoolVar`/logical constraints are present.
83
+ * - `"glpk"` (`import "@ohtaman/washi/solvers/glpk"`): Supports LP and MIP, and `m.check()` on purely
84
+ * linear models via LP feasibility fallback. Throws on quadratic objectives, `BoolVar`/logical constraints,
85
+ * or `initialValue` warm starts.
86
+ * - `"z3"` (`import "@ohtaman/washi/solvers/z3"`): Supports SMT satisfiability (`m.check()`), optimization (`m.solve()`),
87
+ * `BoolVar`/logical constraints (`and`, `or`, `not`, `implies`, `xor`), and unsatisfiable-core extraction
88
+ * (`conflicts` / `unsatCore`). Throws on quadratic objectives or `initialValue` warm starts.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { Model, expr, sum, dot, maximize } from "@ohtaman/washi";
93
+ *
94
+ * const m = new Model("ProductionPlan");
95
+ * const qty = m.integer(["desk", "chair"] as const, { lb: 0, ub: 100 });
96
+ * const setup = m.binary("setup", { initialValue: 1 });
97
+ *
98
+ * m.objective(maximize(expr`${dot({ desk: 30, chair: 50 }, qty)} - 20 * ${setup}`));
99
+ * m.constraint(expr`${dot({ desk: 1, chair: 2 }, qty)} <= 40`, "wood_cap");
100
+ * m.constraint(expr`${sum(Object.values(qty))} <= 30 * ${setup}`, "require_setup");
101
+ *
102
+ * const status = await m.solve();
103
+ * const report = m.validateSolution();
104
+ * const solvedQty = m.getValues(qty);
105
+ * ```
106
+ */
32
107
  export declare class Model {
33
108
  name: string;
34
- sense: OptimizationSense;
35
- objective: LinExpr | QuadExpr;
109
+ private _sense;
110
+ private _objectiveExpr;
36
111
  variables: Var[];
37
112
  constraints: Constraint[];
38
113
  boolVars: BoolVar[];
39
114
  logicalConstraints: LogicalConstraint[];
40
- unsatCore: string[];
115
+ unsatCore: readonly string[] | undefined;
41
116
  values: Map<string, number | boolean>;
42
117
  private varMapByName;
118
+ private varPrefixCounters;
43
119
  private boolVarMapByName;
44
120
  private boolVarPrefixCounters;
45
121
  private constrMapByName;
122
+ private constrPrefixCounters;
123
+ private logicalConstrMapByName;
124
+ private logicalConstrCounter;
46
125
  status: SolverStatus;
126
+ terminationStatus: TerminationStatus;
127
+ hasPrimalSolution: boolean;
47
128
  objectiveValue: number | null;
129
+ objectiveBound: number | undefined;
130
+ relGap: number | undefined;
131
+ mipGap: number | undefined;
132
+ absGap: number | undefined;
48
133
  runTime: number;
49
134
  solution: SolverSolution | null;
50
135
  solver: Solver | null;
136
+ private hasSolutionState;
137
+ private modelRevision;
138
+ private activeOperationId;
139
+ private batchDepth;
140
+ private batchMutated;
141
+ private batchUndoActions;
51
142
  constructor(nameOrOptions?: string | ModelOptions, maybeOptions?: ModelOptions);
52
- get vars(): Var[];
53
- get constrs(): Constraint[];
143
+ get sense(): OptimizationSense;
144
+ set sense(value: OptimizationSense);
145
+ get objectiveExpr(): LinExpr | QuadExpr;
146
+ set objectiveExpr(value: LinExpr | QuadExpr | Constraint);
147
+ /**
148
+ * User-friendly alias for unsatCore.
149
+ * Returns a subset of conflicting constraint names causing infeasibility,
150
+ * or undefined if not diagnosed, not applicable, or satisfiable.
151
+ */
152
+ get conflicts(): readonly string[] | undefined;
54
153
  get numVars(): number;
55
154
  get numConstrs(): number;
155
+ /**
156
+ * Clears stored solution and diagnostic fields on the model and its entities.
157
+ */
158
+ private clearSolutionFields;
159
+ /**
160
+ * Records a model mutation, invalidating any stored solution state and in-flight solver executions.
161
+ */
162
+ private recordModelMutation;
163
+ /**
164
+ * @internal Notifies the model that an owned entity (e.g., Var bounds/type or Constraint RHS/sense) was mutated.
165
+ */
166
+ notifyMutation(): void;
167
+ /**
168
+ * Reset prior solution and diagnostic state to avoid stale data leakage across runs,
169
+ * and invalidate any in-flight solve() or check() execution.
170
+ */
171
+ resetSolutionState(): void;
172
+ /**
173
+ * Executes a multi-item model mutation atomically so failed batch edits neither leave
174
+ * partial entities registered nor invalidate prior solved / in-flight state.
175
+ */
176
+ private runTransactionalBatch;
56
177
  /**
57
178
  * Internal generator for domain-specific variables
58
179
  */
59
180
  private createDomainVars;
60
181
  /**
61
- * Create 0-1 binary variable(s) (x in {0, 1}).
62
- * Supports:
63
- * - m.binary("x") -> Var
64
- * - m.binary(5) -> Var[]
65
- * - m.binary(["a", "b"]) -> Record<string, Var>
66
- * - m.binary(rows, cols) -> Record<string, Record<string, Var>>
67
- */
68
- binary(name: string): Var;
69
- binary(count: number, options?: {
70
- prefix?: string;
71
- name?: string;
72
- }): Var[];
73
- binary<K extends string | number>(keys: K[] | Iterable<K>, options?: {
74
- prefix?: string;
75
- name?: string;
76
- }): Record<K, Var>;
77
- binary<R extends string | number, C extends string | number>(dim1: R[] | number, dim2: C[] | number, options?: {
78
- prefix?: string;
79
- name?: string;
80
- }): Record<R, Record<C, Var>>;
81
- /**
82
- * Create integer variable(s) (y in Z).
83
- * Supports:
84
- * - m.integer("y", { lb: 0, ub: 10 }) -> Var
85
- * - m.integer(5, { lb: 0 }) -> Var[]
86
- * - m.integer(["a", "b"], { lb: 0, ub: 5 }) -> Record<string, Var>
87
- * - m.integer(rows, cols, options) -> Record<string, Record<string, Var>>
88
- */
89
- integer(name: string, options?: BoundsOptions): Var;
182
+ * Create 0-1 binary decision variable(s) ($x \in \{0, 1\}$).
183
+ *
184
+ * **Scalar & indexed container overloads**:
185
+ * - `m.binary("x", options?)` or `m.binary(options?)` -> `Var`
186
+ * - `m.binary(count, options?)` -> `Var[]`
187
+ * - `m.binary(keys, options?)` -> `Record<K, Var>`
188
+ * - `m.binary(rowsCount, colsCount, options?)` -> `Var[][]`
189
+ * - `m.binary(rowsCount, colKeys, options?)` -> `Array<Record<C, Var>>`
190
+ * - `m.binary(rowKeys, colsCount, options?)` -> `Record<R, Var[]>`
191
+ * - `m.binary(rowKeys, colKeys, options?)` -> `Record<R, Record<C, Var>>`
192
+ *
193
+ * **Warm-start (`initialValue`) semantics**:
194
+ * - `options.initialValue` supplies an optional finite primal hint (`0` or `1` within tolerance `1e-6`),
195
+ * kept distinct from solved `v.value`.
196
+ * - Supported by HiGHS (`supportsWarmStart: true`); throws on GLPK and Z3.
197
+ *
198
+ * @example
199
+ * ```ts
200
+ * const m = new Model("BinaryVars");
201
+ * const b = m.binary("b", { initialValue: 1 }); // Var
202
+ * const vec = m.binary(4, { prefix: "u" }); // Var[]
203
+ * const grid = m.binary(2, 3, { prefix: "g" }); // Var[][]
204
+ * const byShift = m.binary(["day", "night"] as const); // Record<"day" | "night", Var>
205
+ * ```
206
+ */
207
+ binary(name?: string, options?: BinaryOptions): Var;
208
+ binary(options: BinaryOptions): Var;
209
+ binary(count: number, options?: BinaryOptions): Var[];
210
+ binary<K extends string | number>(keys: KeyCollection<K>, options?: BinaryOptions): Record<K, Var>;
211
+ binary(rows: number, cols: number, options?: BinaryOptions): Var[][];
212
+ binary<C extends string | number>(rows: number, cols: KeyCollection<C>, options?: BinaryOptions): Array<Record<C, Var>>;
213
+ binary<R extends string | number>(rows: KeyCollection<R>, cols: number, options?: BinaryOptions): Record<R, Var[]>;
214
+ binary<R extends string | number, C extends string | number>(rows: KeyCollection<R>, cols: KeyCollection<C>, options?: BinaryOptions): Record<R, Record<C, Var>>;
215
+ /**
216
+ * Create integer decision variable(s) ($y \in \mathbb{Z}$, default bounds `lb: 0`, `ub: Infinity`).
217
+ *
218
+ * **Scalar & indexed container overloads**:
219
+ * - `m.integer("y", options?)` or `m.integer(options)` -> `Var`
220
+ * - `m.integer(count, options?)` -> `Var[]`
221
+ * - `m.integer(keys, options?)` -> `Record<K, Var>`
222
+ * - `m.integer(rowsCount, colsCount, options?)` -> `Var[][]`
223
+ * - `m.integer(rowsCount, colKeys, options?)` -> `Array<Record<C, Var>>`
224
+ * - `m.integer(rowKeys, colsCount, options?)` -> `Record<R, Var[]>`
225
+ * - `m.integer(rowKeys, colKeys, options?)` -> `Record<R, Record<C, Var>>`
226
+ *
227
+ * **Warm-start (`initialValue`) semantics**:
228
+ * - `options.initialValue` supplies an optional finite integer primal hint within tolerance `1e-6` of `[lb, ub]`,
229
+ * kept distinct from solved `v.value`.
230
+ * - Supported by HiGHS (`supportsWarmStart: true`); throws on GLPK and Z3.
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * const m = new Model("IntegerVars");
235
+ * const n = m.integer("n", { lb: 0, ub: 10, initialValue: 4 }); // Var
236
+ * const counts = m.integer(3, { lb: 0, prefix: "k" }); // Var[]
237
+ * const matrix = m.integer(2, 2, { lb: 0, prefix: "m" }); // Var[][]
238
+ * const byItem = m.integer(["desk", "chair"] as const, { lb: 0, ub: 50 }); // Record<"desk" | "chair", Var>
239
+ * ```
240
+ */
241
+ integer(name?: string, options?: BoundsOptions): Var;
242
+ integer(options: BoundsOptions): Var;
90
243
  integer(count: number, options?: BoundsOptions): Var[];
91
- integer<K extends string | number>(keys: K[] | Iterable<K>, options?: BoundsOptions): Record<K, Var>;
92
- integer<R extends string | number, C extends string | number>(dim1: R[] | number, dim2: C[] | number, options?: BoundsOptions): Record<R, Record<C, Var>>;
244
+ integer<K extends string | number>(keys: KeyCollection<K>, options?: BoundsOptions): Record<K, Var>;
245
+ integer(rows: number, cols: number, options?: BoundsOptions): Var[][];
246
+ integer<C extends string | number>(rows: number, cols: KeyCollection<C>, options?: BoundsOptions): Array<Record<C, Var>>;
247
+ integer<R extends string | number>(rows: KeyCollection<R>, cols: number, options?: BoundsOptions): Record<R, Var[]>;
248
+ integer<R extends string | number, C extends string | number>(rows: KeyCollection<R>, cols: KeyCollection<C>, options?: BoundsOptions): Record<R, Record<C, Var>>;
93
249
  /**
94
- * Create continuous (real) variable(s) (z in R).
95
- * Supports:
96
- * - m.continuous("z", { lb: 0 }) -> Var
97
- * - m.continuous(5, { lb: 0 }) -> Var[]
98
- * - m.continuous(["a", "b"], { lb: 0 }) -> Record<string, Var>
99
- * - m.continuous(rows, cols, options) -> Record<string, Record<string, Var>>
250
+ * Create continuous (real) decision variable(s) ($z \in \mathbb{R}$, default bounds `lb: 0`, `ub: Infinity`).
251
+ *
252
+ * **Scalar & indexed container overloads**:
253
+ * - `m.continuous("z", options?)` or `m.continuous(options)` -> `Var`
254
+ * - `m.continuous(count, options?)` -> `Var[]`
255
+ * - `m.continuous(keys, options?)` -> `Record<K, Var>`
256
+ * - `m.continuous(rowsCount, colsCount, options?)` -> `Var[][]`
257
+ * - `m.continuous(rowsCount, colKeys, options?)` -> `Array<Record<C, Var>>`
258
+ * - `m.continuous(rowKeys, colsCount, options?)` -> `Record<R, Var[]>`
259
+ * - `m.continuous(rowKeys, colKeys, options?)` -> `Record<R, Record<C, Var>>`
260
+ *
261
+ * **Warm-start (`initialValue`) semantics**:
262
+ * - `options.initialValue` supplies an optional finite primal hint within tolerance `1e-6` of `[lb, ub]`,
263
+ * kept distinct from solved `v.value`.
264
+ * - Supported by HiGHS (`supportsWarmStart: true`); throws on GLPK and Z3.
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * const m = new Model("ContinuousVars");
269
+ * const x = m.continuous("x", { lb: 0, ub: 100, initialValue: 25 }); // Var
270
+ * const vec = m.continuous(4, { lb: 0, prefix: "v" }); // Var[]
271
+ * const flow = m.continuous(2, 3, { lb: 0, prefix: "f" }); // Var[][]
272
+ * const alloc = m.continuous(["A", "B"] as const, { lb: 0 }); // Record<"A" | "B", Var>
273
+ * ```
100
274
  */
101
- continuous(name: string, options?: BoundsOptions): Var;
275
+ continuous(name?: string, options?: BoundsOptions): Var;
276
+ continuous(options: BoundsOptions): Var;
102
277
  continuous(count: number, options?: BoundsOptions): Var[];
103
- continuous<K extends string | number>(keys: K[] | Iterable<K>, options?: BoundsOptions): Record<K, Var>;
104
- continuous<R extends string | number, C extends string | number>(dim1: R[] | number, dim2: C[] | number, options?: BoundsOptions): Record<R, Record<C, Var>>;
105
- /**
106
- * Create Boolean (propositional logic) variable(s) for SMT / SAT modeling.
107
- * Supports:
108
- * - m.bool("isNight") -> BoolVar
109
- * - m.bool() -> BoolVar
110
- * - m.bool(5) -> BoolVar[]
111
- * - m.bool(["flagA", "flagB"]) -> Record<string, BoolVar>
112
- * - m.bool(rows, cols) -> Record<string, Record<string, BoolVar>>
113
- */
114
- bool(name?: string): BoolVar;
115
- bool(count: number, options?: {
116
- prefix?: string;
117
- name?: string;
118
- }): BoolVar[];
119
- bool<K extends string | number>(keys: K[] | Iterable<K>, options?: {
120
- prefix?: string;
121
- name?: string;
122
- }): Record<K, BoolVar>;
123
- bool<R extends string | number, C extends string | number>(dim1: R[] | number, dim2: C[] | number, options?: {
124
- prefix?: string;
125
- name?: string;
126
- }): Record<R, Record<C, BoolVar>>;
278
+ continuous<K extends string | number>(keys: KeyCollection<K>, options?: BoundsOptions): Record<K, Var>;
279
+ continuous(rows: number, cols: number, options?: BoundsOptions): Var[][];
280
+ continuous<C extends string | number>(rows: number, cols: KeyCollection<C>, options?: BoundsOptions): Array<Record<C, Var>>;
281
+ continuous<R extends string | number>(rows: KeyCollection<R>, cols: number, options?: BoundsOptions): Record<R, Var[]>;
282
+ continuous<R extends string | number, C extends string | number>(rows: KeyCollection<R>, cols: KeyCollection<C>, options?: BoundsOptions): Record<R, Record<C, Var>>;
283
+ /**
284
+ * Create propositional Boolean variable(s) (`BoolVar`: `true` / `false`) for SMT / SAT logical modeling.
285
+ *
286
+ * **Scalar & indexed container overloads**:
287
+ * - `m.bool("flag", options?)` or `m.bool(options?)` -> `BoolVar`
288
+ * - `m.bool(count, options?)` -> `BoolVar[]`
289
+ * - `m.bool(keys, options?)` -> `Record<K, BoolVar>`
290
+ * - `m.bool(rowsCount, colsCount, options?)` -> `BoolVar[][]`
291
+ * - `m.bool(rowsCount, colKeys, options?)` -> `Array<Record<C, BoolVar>>`
292
+ * - `m.bool(rowKeys, colsCount, options?)` -> `Record<R, BoolVar[]>`
293
+ * - `m.bool(rowKeys, colKeys, options?)` -> `Record<R, Record<C, BoolVar>>`
294
+ *
295
+ * **Solver capability note**:
296
+ * - Logical constraints over `BoolVar` (`and`, `or`, `not`, `implies`, `xor`) require an SMT-capable solver
297
+ * such as Z3 (`new Model("...", { solver: "z3" })` after `import "@ohtaman/washi/solvers/z3"`).
298
+ * - LP/MIP solvers (HiGHS, GLPK) throw if logical constraints are present. For 0-1 arithmetic variables
299
+ * in LP/MIP (or Big-M `m.indicator()`), use `m.binary()` instead.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * import "@ohtaman/washi/solvers/z3";
304
+ *
305
+ * const m = new Model("BoolVars", { solver: "z3" });
306
+ * const vip = m.bool("vip"); // BoolVar
307
+ * const flags = m.bool(3, { prefix: "f" }); // BoolVar[]
308
+ * const grid = m.bool(2, 2, { prefix: "g" }); // BoolVar[][]
309
+ * const byRole = m.bool(["admin", "guest"] as const); // Record<"admin" | "guest", BoolVar>
310
+ * m.constraint(implies(vip, flags[0]), "vip_flag");
311
+ * ```
312
+ */
313
+ bool(name?: string, options?: VarNameOptions): BoolVar;
314
+ bool(options: VarNameOptions): BoolVar;
315
+ bool(count: number, options?: VarNameOptions): BoolVar[];
316
+ bool<K extends string | number>(keys: KeyCollection<K>, options?: VarNameOptions): Record<K, BoolVar>;
317
+ bool(rows: number, cols: number, options?: VarNameOptions): BoolVar[][];
318
+ bool<C extends string | number>(rows: number, cols: KeyCollection<C>, options?: VarNameOptions): Array<Record<C, BoolVar>>;
319
+ bool<R extends string | number>(rows: KeyCollection<R>, cols: number, options?: VarNameOptions): Record<R, BoolVar[]>;
320
+ bool<R extends string | number, C extends string | number>(rows: KeyCollection<R>, cols: KeyCollection<C>, options?: VarNameOptions): Record<R, Record<C, BoolVar>>;
127
321
  private hasVarName;
322
+ private getNextVarName;
128
323
  private getNextBoolVarName;
324
+ private hasConstraintName;
325
+ private hasBoolVarName;
326
+ private getNextConstrName;
327
+ private getNextLogicalConstrName;
129
328
  private createBoolVar;
130
329
  /**
131
330
  * Internal variable creator
@@ -144,39 +343,86 @@ export declare class Model {
144
343
  */
145
344
  getConstraintByName(name: string): Constraint | undefined;
146
345
  /**
147
- * Set the objective function
346
+ * Find a logical constraint by its name
148
347
  */
149
- setObjective(expr: LinExpr | QuadExpr | Var | number | string | Constraint, sense?: OptimizationSense): void;
348
+ getLogicalConstraintByName(name: string): LogicalConstraint | undefined;
150
349
  /**
151
- * Set objective to maximize
350
+ * Get the current objective expression, or set the objective function and direction (`maximize(...)` / `minimize(...)`).
351
+ * Calling `objective(spec)` replaces any previously defined objective and returns `this` for chaining.
352
+ *
353
+ * **Formulation & solver capability notes**:
354
+ * - Supports linear (`LinExpr`, `Var`, `number`, formula string) and quadratic (`QuadExpr`: `^2`, `${x} * ${y}`) expressions.
355
+ * - Quadratic terms are supported in **objectives only** (requires a QP-capable solver such as HiGHS; throws on GLPK and Z3).
356
+ * - Passing a comparison `Constraint` (`<=`, `>=`, `==`) throws an Error.
357
+ *
358
+ * @example
359
+ * ```ts
360
+ * const m = new Model("ObjectiveExample");
361
+ * const chairs = m.integer("chairs", { lb: 0 });
362
+ * const tables = m.integer("tables", { lb: 0 });
363
+ *
364
+ * m.objective(maximize(expr`30 * ${chairs} + 50 * ${tables}`));
365
+ * const currentExpr = m.objective();
366
+ * ```
152
367
  */
153
- maximize(expr: LinExpr | QuadExpr | Var | number | string | Constraint): void;
368
+ objective(): LinExpr | QuadExpr;
369
+ objective(spec: ObjectiveSpec): this;
154
370
  /**
155
- * Set objective to minimize
371
+ * Internal objective setter.
156
372
  */
157
- minimize(expr: LinExpr | QuadExpr | Var | number | string | Constraint): void;
373
+ private applyObjective;
158
374
  /**
159
- * Constrain the model with linear, boolean, or string formula constraints (primary default API).
160
- * Supports single constraint, array of constraints, and fluent chaining:
161
- * - m.constrain(expr`${desks} + 2 * ${chairs} <= 40`, "wood")
162
- * - m.constrain(items.map(i => expr`${x[i]} <= 10`))
163
- * - m.constrain(c1).constrain(c2)
375
+ * Register linear comparison constraint(s) (`<=`, `>=`, `==`), SMT logical constraint(s) (`BoolVar`, `BoolExpr`),
376
+ * or constraint formula string(s) on the model. Chainable: returns `this`.
377
+ *
378
+ * **Formulation & solver capability notes**:
379
+ * - Rejects raw arithmetic expressions (`LinExpr`, `QuadExpr`) without a comparison operator and quadratic constraints.
380
+ * - Logical constraints (`BoolVar`, `and`, `or`, `not`, `implies`, `xor`) require an SMT-capable solver (`{ solver: "z3" }`);
381
+ * LP/MIP solvers (HiGHS, GLPK) throw if logical constraints are present.
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * const m = new Model("ConstraintExample");
386
+ * const desks = m.integer("desks", { lb: 0 });
387
+ * const chairs = m.integer("chairs", { lb: 0 });
388
+ * const x = m.continuous(3, { lb: 0, prefix: "x" });
389
+ *
390
+ * m.constraint(expr`${desks} + 2 * ${chairs} <= 40`, "wood");
391
+ * m.constraint(x.map((v) => expr`${v} <= 10`));
392
+ * m.constraint(desks.ge(2)).constraint(chairs.ge(4));
393
+ * ```
164
394
  */
165
- constrain(constraint: Constraint | LinExpr | QuadExpr | BoolExpr | string, name?: string): this;
166
- constrain(constraints: (Constraint | LinExpr | QuadExpr | BoolExpr | string)[]): this;
395
+ constraint(constraint: ConstraintItem | LinExpr | QuadExpr, name?: string): this;
396
+ constraint(constraints: ReadonlyArray<ConstraintItem | LinExpr | QuadExpr>): this;
167
397
  /**
168
- * Extract primal solution values directly into plain primitives:
169
- * - m.getValues(x) -> number | null
170
- * - m.getValues(p) -> boolean | null
171
- * - m.getValues([x, y]) -> (number | null)[]
172
- * - m.getValues([p, q]) -> (boolean | null)[]
173
- * - m.getValues(record) -> Record<string, number | boolean | null>
174
- * - m.getValues(matrix) -> Record<string, Record<string, number | boolean | null>>
398
+ * Extract primal solution values directly into plain primitives, preserving container shapes:
399
+ * - `m.getValues(x)` -> `number | null`
400
+ * - `m.getValues(p)` -> `boolean | null`
401
+ * - `m.getValues([x, y])` -> `(number | null)[]`
402
+ * - `m.getValues([[x11, x12], [x21, x22]])` -> `(number | null)[][]`
403
+ * - `m.getValues(record)` -> `Record<K, number | boolean | null>`
404
+ * - `m.getValues(matrix)` -> `Record<R, Record<C, number | boolean | null>>`
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * const m = new Model("GetValuesExample");
409
+ * const qty = m.integer(["desk", "chair"] as const, { lb: 0, ub: 10 });
410
+ * m.objective(maximize(expr`30 * ${qty.desk} + 50 * ${qty.chair}`));
411
+ * m.constraint(expr`${qty.desk} + ${qty.chair} <= 10`);
412
+ * await m.solve();
413
+ * const values = m.getValues(qty); // Record<"desk" | "chair", number | null>
414
+ * ```
175
415
  */
176
416
  getValues(item: Var): number | null;
177
417
  getValues(item: BoolVar): boolean | null;
178
- getValues(items: Var[]): (number | null)[];
179
- getValues(items: BoolVar[]): (boolean | null)[];
418
+ getValues(items: ReadonlyArray<Var>): (number | null)[];
419
+ getValues(items: ReadonlyArray<BoolVar>): (boolean | null)[];
420
+ getValues(items: ReadonlyArray<ReadonlyArray<Var>>): (number | null)[][];
421
+ getValues(items: ReadonlyArray<ReadonlyArray<BoolVar>>): (boolean | null)[][];
422
+ getValues<C extends string | number>(items: ReadonlyArray<Record<C, Var>>): Array<Record<C, number | null>>;
423
+ getValues<C extends string | number>(items: ReadonlyArray<Record<C, BoolVar>>): Array<Record<C, boolean | null>>;
424
+ getValues<R extends string | number>(items: Record<R, ReadonlyArray<Var>>): Record<R, (number | null)[]>;
425
+ getValues<R extends string | number>(items: Record<R, ReadonlyArray<BoolVar>>): Record<R, (boolean | null)[]>;
180
426
  getValues<K extends string | number>(items: Record<K, Var>): Record<K, number | null>;
181
427
  getValues<K extends string | number>(items: Record<K, BoolVar>): Record<K, boolean | null>;
182
428
  getValues<R extends string | number, C extends string | number>(items: Record<R, Record<C, Var>>): Record<R, Record<C, number | null>>;
@@ -186,54 +432,155 @@ export declare class Model {
186
432
  */
187
433
  private addConstraint;
188
434
  /**
189
- * Universal classical fluent adder for constraints, variables, or batches.
190
- * Enables:
191
- * - m.add(x.mul(2).add(y).le(10))
192
- * - m.add(c`${x} + ${y} <= 10`)
193
- * - m.add("x + y <= 10")
194
- * - m.add([c1, c2, c3])
195
- * - m.add(new Var(...))
196
- * - m.add(c1).add(c2) (fluent chaining)
197
- */
198
- add(constraint: Constraint, name?: string): this;
199
- add(expr: BoolExpr, name?: string): this;
200
- add(strConstraint: string, name?: string): this;
201
- add(variable: Var): this;
202
- add(items: (Constraint | BoolExpr | string | Var)[]): this;
203
- /**
204
- * Add an indicator constraint via Big-M auto-linearization:
205
- * "If binVar == activeValue, then constraint holds"
435
+ * Add an indicator constraint via floating-point Big-M auto-linearization:
436
+ * `"If binVar === activeValue, then constraint holds"` (`activeValue` defaults to `1`).
206
437
  *
207
- * Automatically handles <=, >=, and == constraints.
208
- * Enables solving conditional logic in MIP solvers (HiGHS, GLPK) without requiring SMT.
438
+ * **Formulation & solver capability notes**:
439
+ * - Automatically linearizes `<=`, `>=`, and `==` constraints for LP/MIP solvers (HiGHS, GLPK)
440
+ * under standard floating-point feasibility tolerances (`==` generates `_le` and `_ge` rows).
441
+ * - Variables appearing in `constraint` must have finite bounds (`lb`/`ub`) to derive a safe tight Big-M
442
+ * automatically, unless an explicit `{ M }` override is supplied in `options`.
443
+ * - Because Big-M rows are floating-point linear relaxations, they do not guarantee exact rational
444
+ * equivalence in SMT solvers (Z3); use `implies(...)` with `m.bool(...)` when exact SMT diagnosis is required.
445
+ *
446
+ * @example
447
+ * ```ts
448
+ * const m = new Model("IndicatorExample");
449
+ * const b = m.binary("b");
450
+ * const x = m.continuous("x", { lb: 0, ub: 100 });
451
+ * // Enforces x <= 50 when b === 1 (relaxed to x <= 100 when b === 0)
452
+ * m.indicator(b, expr`${x} <= 50`, { activeValue: 1, name: "cap_when_b" });
453
+ * ```
209
454
  */
210
455
  indicator(binVar: Var, constraint: Constraint | LinExpr | QuadExpr, options?: IndicatorOptions): Constraint[];
211
456
  /**
212
- * Export model to CPLEX LP format string
457
+ * Validate model integrity (`validateIntegrity()`) and serialize the model's linear/quadratic objective,
458
+ * linear constraints, and numeric variable bounds/domains (`Continuous`, `Integer`, `Binary`) to a
459
+ * standard CPLEX LP format string with collision-free sanitized identifiers.
460
+ *
461
+ * **Note**: Propositional `BoolVar`s and SMT `logicalConstraints` are not part of the CPLEX LP format.
462
+ *
463
+ * @example
464
+ * ```ts
465
+ * const m = new Model("LpExportExample");
466
+ * const x = m.integer("x", { lb: 0, ub: 10 });
467
+ * m.objective(maximize(expr`5 * ${x}`));
468
+ * m.constraint(expr`${x} <= 8`, "cap");
469
+ * const lpText = m.toLpString();
470
+ * ```
213
471
  */
214
472
  toLpString(): string;
215
473
  /**
216
- * Solve the optimization model using the configured solver (defaults to HiGHS WASM)
217
- * or a solver passed dynamically (e.g., await model.optimize(new HiGHS()))
474
+ * Validates model integrity: variable bounds, ownership, numeric sanity, and unique constraint names.
475
+ * Throws an Error with actionable explanation if any validation rule is violated.
218
476
  */
219
- optimize(solverOrOptions?: Solver | string | SolveOptions, options?: SolveOptions): Promise<SolverStatus>;
477
+ validateIntegrity(): void;
478
+ private ensureExecutionValid;
479
+ private wrapSolveOptions;
480
+ private hasPrimalFromResult;
220
481
  /**
221
- * Convenience alias for optimize():
222
- * await model.solve()
223
- * await model.solve(new HiGHS())
224
- * await model.solve(new GLPK())
225
- * await model.solve(new RemoteSolver({ url: "..." }))
482
+ * Resolves the target solver and execution options without mutating caller-owned objects,
483
+ * stripping the routing `solver` field from the returned `SolverOptions`.
484
+ */
485
+ private resolveSolverAndOptions;
486
+ /**
487
+ * Solve the optimization model using the configured solver (defaults to HiGHS WASM)
488
+ * or a solver passed dynamically (e.g., `await m.solve("glpk")` or `await m.solve({ timeLimit: 10 })`).
489
+ *
490
+ * **Return status (`SolverStatus`)**:
491
+ * - Built-in optimization solvers return `"Optimal"`, `"Feasible"`, `"Infeasible"`, `"Unbounded"`,
492
+ * `"TimeLimit"`, `"IterationLimit"`, `"Error"`, `"Unknown"`, or `"NotSolved"` (`"Sat"` / `"Unsat"`
493
+ * are included in `SolverStatus` for custom/satisfiability adapters).
494
+ * - When a time-, iteration-, or solution-limited run (or an interrupted solve) has found a valid
495
+ * primal incumbent, `solve()` returns `"Feasible"` (`m.hasPrimalSolution === true`, with the exact
496
+ * stopping reason in `m.terminationStatus`).
497
+ * - After solving, read primal/dual values via `x.value`, `m.getValues(...)`, `m.objectiveValue`,
498
+ * `constr.dual`, `constr.slack`, and `x.reducedCost`, and verify primal feasibility with `m.validateSolution()`.
499
+ *
500
+ * **Solver capability preconditions**:
501
+ * - Quadratic objectives (`QuadExpr`) require `supportsQP` (supported by HiGHS; throws on GLPK and Z3).
502
+ * - Logical constraints (`BoolVar`, `and`, `or`, `not`, `implies`, `xor`) require `supportsSMT`
503
+ * (supported by Z3; throws on HiGHS and GLPK).
504
+ * - Primal `initialValue` warm starts require `supportsWarmStart` (supported by HiGHS; throws on GLPK and Z3).
505
+ * - Mutating the model or starting a newer `solve()` / `check()` while in flight discards the stale
506
+ * result and rejects the pending promise.
507
+ *
508
+ * @example
509
+ * ```ts
510
+ * const m = new Model("SolveExample");
511
+ * const x = m.integer("x", { lb: 0, ub: 50, initialValue: 10 });
512
+ * const y = m.integer("y", { lb: 0, ub: 50 });
513
+ * m.objective(maximize(expr`30 * ${x} + 50 * ${y}`));
514
+ * m.constraint(expr`${x} + 2 * ${y} <= 40`, "resource_limit");
515
+ *
516
+ * const status = await m.solve();
517
+ * const report = m.validateSolution();
518
+ * const obj = m.objectiveValue;
519
+ * ```
226
520
  */
227
521
  solve(solverOrOptions?: Solver | string | SolveOptions, options?: SolveOptions): Promise<SolverStatus>;
228
522
  /**
229
- * Check satisfiability of the model without requiring an objective function.
230
- * Can be used to verify feasibility or diagnose infeasibilities / unsat core.
523
+ * Check satisfiability / feasibility of the model without requiring an objective function.
524
+ *
525
+ * Returns `CheckResult` (`{ status: "Sat" | "Unsat" | "Unknown", values, conflicts?, unsatCore?, runTime? }`).
526
+ *
527
+ * **LP feasibility fallback vs. Z3 requirement**:
528
+ * - **Linear models (`m.check()` fallback)**: For models containing only linear arithmetic constraints,
529
+ * `m.check()` works with any solver (including the default HiGHS and GLPK) by falling back to a
530
+ * zero-objective feasibility `solve()` without mutating `m.objectiveExpr` or `m.sense`.
531
+ * - **Logical constraints & `unsatCore` (requires Z3)**: Models containing `BoolVar` or logical
532
+ * constraints (`and`, `or`, `not`, `implies`, `xor`) require an SMT-capable solver (`{ solver: "z3" }`
533
+ * after `import "@ohtaman/washi/solvers/z3"`). Unsatisfiable-core extraction (`result.conflicts` /
534
+ * `result.unsatCore` and `m.conflicts` / `m.unsatCore`) is populated only when an unsat-core-capable
535
+ * solver such as Z3 returns `"Unsat"`, reporting a subset of registered constraint names that conflicts
536
+ * together with the model's fixed variable bounds/domains.
537
+ * - Mutating the model or starting a newer `solve()` / `check()` while in flight discards the stale
538
+ * result and rejects the pending promise.
539
+ *
540
+ * @example
541
+ * ```ts
542
+ * import "@ohtaman/washi/solvers/z3";
543
+ *
544
+ * // 1. Linear feasibility check (works with default HiGHS via LP fallback)
545
+ * const mLin = new Model("LinearCheck");
546
+ * const x = mLin.continuous("x", { lb: 0, ub: 10 });
547
+ * mLin.constraint(expr`${x} >= 4`, "min_x");
548
+ * const linRes = await mLin.check(); // { status: "Sat", values: { x: ... } }
549
+ *
550
+ * // 2. SMT satisfiability & unsatCore diagnosis (requires Z3)
551
+ * const mSmt = new Model("PolicyCheck", { solver: "z3" });
552
+ * const vip = mSmt.bool("vip");
553
+ * const discount = mSmt.integer("discount", { lb: 0, ub: 50 });
554
+ * mSmt.constraint(vip, "is_vip");
555
+ * mSmt.constraint(implies(vip, expr`${discount} >= 20`), "vip_min");
556
+ * mSmt.constraint(expr`${discount} <= 10`, "cap");
557
+ * const smtRes = await mSmt.check(); // { status: "Unsat", conflicts: [...], unsatCore: [...] }
558
+ * ```
559
+ */
560
+ check(solverOrOptions?: Solver | string | SolveOptions, options?: SolveOptions): Promise<CheckResult>;
561
+ /**
562
+ * Independently evaluate and verify variable finiteness, variable bounds (`lb`/`ub`),
563
+ * integer/binary/boolean domains, linear constraint residuals, and logical (SMT/propositional)
564
+ * constraints against the model's current solved values (or an explicit `options.values` map).
565
+ *
566
+ * Returns a `SolutionValidationReport` (`{ valid, complete, maxViolation, violations, violationsByName, uncheckedConstraints, missingVariables, summary }`).
567
+ *
568
+ * **Verification notes**:
569
+ * - Runs purely in JavaScript/TypeScript without requiring any WASM solver runtime.
570
+ * - Verifies primal feasibility of variables and constraints; does not recompute or compare `m.objectiveValue`.
571
+ *
572
+ * @example
573
+ * ```ts
574
+ * const m = new Model("ValidateExample");
575
+ * const x = m.integer("x", { lb: 0, ub: 10 });
576
+ * m.objective(maximize(expr`3 * ${x}`));
577
+ * m.constraint(expr`${x} <= 7`, "cap");
578
+ *
579
+ * await m.solve();
580
+ * const report = m.validateSolution();
581
+ * const isFeasible = report.valid && report.maxViolation <= 1e-6;
582
+ * ```
231
583
  */
232
- check(solverOrOptions?: Solver | string | SolveOptions, options?: SolveOptions): Promise<{
233
- status: "Sat" | "Unsat" | "Unknown";
234
- values: Record<string, number | boolean>;
235
- unsatCore?: string[];
236
- runTime?: number;
237
- }>;
584
+ validateSolution(options?: SolutionValidationOptions): SolutionValidationReport;
238
585
  }
239
586
  //# sourceMappingURL=model.d.ts.map