@bubblyworld/scip-ts 0.0.1
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.md +131 -0
- package/build/scip.js +2 -0
- package/build/scip.wasm +0 -0
- package/dist/index.browser.d.ts +5 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.browser.js +443 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/index.node.d.ts +12 -0
- package/dist/index.node.d.ts.map +1 -0
- package/dist/index.node.js +459 -0
- package/dist/index.node.js.map +1 -0
- package/dist/model/constraint.d.ts +12 -0
- package/dist/model/constraint.d.ts.map +1 -0
- package/dist/model/constraint.js +11 -0
- package/dist/model/constraint.js.map +1 -0
- package/dist/model/expr.d.ts +25 -0
- package/dist/model/expr.d.ts.map +1 -0
- package/dist/model/expr.js +51 -0
- package/dist/model/expr.js.map +1 -0
- package/dist/model/helpers.d.ts +5 -0
- package/dist/model/helpers.d.ts.map +1 -0
- package/dist/model/helpers.js +10 -0
- package/dist/model/helpers.js.map +1 -0
- package/dist/model/index.d.ts +8 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/index.js +7 -0
- package/dist/model/index.js.map +1 -0
- package/dist/model/lp-format.d.ts +11 -0
- package/dist/model/lp-format.d.ts.map +1 -0
- package/dist/model/lp-format.js +122 -0
- package/dist/model/lp-format.js.map +1 -0
- package/dist/model/model.d.ts +30 -0
- package/dist/model/model.d.ts.map +1 -0
- package/dist/model/model.js +75 -0
- package/dist/model/model.js.map +1 -0
- package/dist/model/solution.d.ts +13 -0
- package/dist/model/solution.d.ts.map +1 -0
- package/dist/model/solution.js +14 -0
- package/dist/model/solution.js.map +1 -0
- package/dist/model/types.d.ts +11 -0
- package/dist/model/types.d.ts.map +1 -0
- package/dist/model/types.js +2 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/var.d.ts +28 -0
- package/dist/model/var.d.ts.map +1 -0
- package/dist/model/var.js +43 -0
- package/dist/model/var.js.map +1 -0
- package/dist/module.d.ts +4 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +15 -0
- package/dist/module.js.map +1 -0
- package/dist/solver.d.ts +19 -0
- package/dist/solver.d.ts.map +1 -0
- package/dist/solver.js +108 -0
- package/dist/solver.js.map +1 -0
- package/dist/types.d.ts +42 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
|
|
3
|
+
/** Loads a fresh SCIP WebAssembly module with the given options. */
|
|
4
|
+
async function loadSCIPModule(options) {
|
|
5
|
+
const createModule = await loadSCIPFactory();
|
|
6
|
+
const consoleConfig = options?.console ?? { log: null, error: null };
|
|
7
|
+
const moduleOptions = {
|
|
8
|
+
print: consoleConfig.log ?? (() => { }),
|
|
9
|
+
printErr: consoleConfig.error ?? (() => { }),
|
|
10
|
+
};
|
|
11
|
+
return createModule(moduleOptions);
|
|
12
|
+
}
|
|
13
|
+
async function loadSCIPFactory() {
|
|
14
|
+
const { default: SCIPModuleFactory } = await import(new URL('../build/scip.js', import.meta.url).href);
|
|
15
|
+
return SCIPModuleFactory;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const SCIP_STATUS_MAP = {
|
|
19
|
+
0: 'unknown',
|
|
20
|
+
1: 'optimal',
|
|
21
|
+
2: 'infeasible',
|
|
22
|
+
3: 'unbounded',
|
|
23
|
+
4: 'inforunbd',
|
|
24
|
+
5: 'timelimit',
|
|
25
|
+
6: 'nodelimit',
|
|
26
|
+
7: 'stallnodelimit',
|
|
27
|
+
8: 'gaplimit',
|
|
28
|
+
9: 'sollimit',
|
|
29
|
+
10: 'bestsollimit',
|
|
30
|
+
11: 'restartlimit',
|
|
31
|
+
};
|
|
32
|
+
/** Low-level wrapper around the SCIP optimization solver. */
|
|
33
|
+
let SCIP$1 = class SCIP {
|
|
34
|
+
constructor(module, scipPtr) {
|
|
35
|
+
this.freed = false;
|
|
36
|
+
this.module = module;
|
|
37
|
+
this.scipPtr = scipPtr;
|
|
38
|
+
}
|
|
39
|
+
/** Creates a new SCIP solver instance. */
|
|
40
|
+
static async create(options) {
|
|
41
|
+
const module = await loadSCIPModule(options);
|
|
42
|
+
const scipPtrPtr = module._malloc(4);
|
|
43
|
+
try {
|
|
44
|
+
module.ccall('SCIPcreate', 'number', ['number'], [scipPtrPtr]);
|
|
45
|
+
const scipPtr = module.getValue(scipPtrPtr, 'i32');
|
|
46
|
+
if (scipPtr === 0) {
|
|
47
|
+
throw new Error('SCIPcreate failed to create instance');
|
|
48
|
+
}
|
|
49
|
+
module.ccall('SCIPincludeDefaultPlugins', 'number', ['number'], [scipPtr]);
|
|
50
|
+
return new SCIP(module, scipPtr);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
module._free(scipPtrPtr);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Reads a problem from a string in the given format (e.g., 'lp', 'mps'). */
|
|
57
|
+
async readProblemFromString(content, format) {
|
|
58
|
+
this.ensureNotFreed();
|
|
59
|
+
const filename = `/tmp/problem.${format}`;
|
|
60
|
+
this.module.FS.writeFile(filename, content);
|
|
61
|
+
try {
|
|
62
|
+
this.module.ccall('SCIPreadProb', 'number', ['number', 'string', 'string'], [this.scipPtr, filename, format]);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
try {
|
|
66
|
+
this.module.FS.unlink(filename);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore cleanup errors
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Solves the loaded problem and returns the result. */
|
|
74
|
+
async solve() {
|
|
75
|
+
this.ensureNotFreed();
|
|
76
|
+
this.module.ccall('SCIPsolve', 'number', ['number'], [this.scipPtr]);
|
|
77
|
+
const statusCode = this.module.ccall('SCIPgetStatus', 'number', ['number'], [this.scipPtr]);
|
|
78
|
+
const status = SCIP_STATUS_MAP[statusCode] ?? 'unknown';
|
|
79
|
+
const result = { status };
|
|
80
|
+
if (status === 'optimal' || status === 'timelimit' || status === 'gaplimit' ||
|
|
81
|
+
status === 'sollimit' || status === 'bestsollimit') {
|
|
82
|
+
const solPtr = this.module.ccall('SCIPgetBestSol', 'number', ['number'], [this.scipPtr]);
|
|
83
|
+
if (solPtr !== 0) {
|
|
84
|
+
result.objective = this.module.ccall('SCIPgetSolOrigObj', 'number', ['number', 'number'], [this.scipPtr, solPtr]);
|
|
85
|
+
result.solution = this.extractSolution(solPtr);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
extractSolution(solPtr) {
|
|
91
|
+
const solution = new Map();
|
|
92
|
+
const nVars = this.module.ccall('SCIPgetNOrigVars', 'number', ['number'], [this.scipPtr]);
|
|
93
|
+
const varsPtr = this.module.ccall('SCIPgetOrigVars', 'number', ['number'], [this.scipPtr]);
|
|
94
|
+
for (let i = 0; i < nVars; i++) {
|
|
95
|
+
const varPtr = this.module.getValue(varsPtr + i * 4, 'i32');
|
|
96
|
+
const namePtr = this.module.ccall('SCIPvarGetName', 'number', ['number'], [varPtr]);
|
|
97
|
+
const name = this.module.UTF8ToString(namePtr);
|
|
98
|
+
const value = this.module.ccall('SCIPgetSolVal', 'number', ['number', 'number', 'number'], [this.scipPtr, solPtr, varPtr]);
|
|
99
|
+
solution.set(name, value);
|
|
100
|
+
}
|
|
101
|
+
return solution;
|
|
102
|
+
}
|
|
103
|
+
/** Frees the SCIP instance. Safe to call multiple times. */
|
|
104
|
+
free() {
|
|
105
|
+
if (this.freed) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const scipPtrPtr = this.module._malloc(4);
|
|
109
|
+
try {
|
|
110
|
+
this.module.setValue(scipPtrPtr, this.scipPtr, 'i32');
|
|
111
|
+
this.module.ccall('SCIPfree', 'number', ['number'], [scipPtrPtr]);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
this.module._free(scipPtrPtr);
|
|
115
|
+
}
|
|
116
|
+
this.freed = true;
|
|
117
|
+
}
|
|
118
|
+
ensureNotFreed() {
|
|
119
|
+
if (this.freed) {
|
|
120
|
+
throw new Error('SCIP instance has been freed');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** A linear constraint: expr sense rhs (e.g., x + y <= 10). */
|
|
126
|
+
class Constraint {
|
|
127
|
+
/** @internal Use leq(), geq(), or eq() methods on expressions instead. */
|
|
128
|
+
constructor(expr, sense, rhs, name) {
|
|
129
|
+
this.expr = expr;
|
|
130
|
+
this.sense = sense;
|
|
131
|
+
this.rhs = rhs;
|
|
132
|
+
this.name = name;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** A linear expression: sum of terms plus a constant. */
|
|
137
|
+
class LinExpr {
|
|
138
|
+
/** @internal Use variable arithmetic methods (plus, minus, times) instead. */
|
|
139
|
+
constructor(terms, constant) {
|
|
140
|
+
this.terms = terms;
|
|
141
|
+
this.constant = constant;
|
|
142
|
+
}
|
|
143
|
+
/** Returns this + other. */
|
|
144
|
+
plus(other) {
|
|
145
|
+
if (typeof other === 'number') {
|
|
146
|
+
return new LinExpr(this.terms, this.constant + other);
|
|
147
|
+
}
|
|
148
|
+
if (other instanceof LinExpr) {
|
|
149
|
+
return new LinExpr([...this.terms, ...other.terms], this.constant + other.constant);
|
|
150
|
+
}
|
|
151
|
+
return new LinExpr([...this.terms, { coeff: 1, var: other }], this.constant);
|
|
152
|
+
}
|
|
153
|
+
/** Returns this - other. */
|
|
154
|
+
minus(other) {
|
|
155
|
+
if (typeof other === 'number') {
|
|
156
|
+
return new LinExpr(this.terms, this.constant - other);
|
|
157
|
+
}
|
|
158
|
+
if (other instanceof LinExpr) {
|
|
159
|
+
const negatedTerms = other.terms.map((t) => ({ coeff: -t.coeff, var: t.var }));
|
|
160
|
+
return new LinExpr([...this.terms, ...negatedTerms], this.constant - other.constant);
|
|
161
|
+
}
|
|
162
|
+
return new LinExpr([...this.terms, { coeff: -1, var: other }], this.constant);
|
|
163
|
+
}
|
|
164
|
+
/** Returns coeff * this. */
|
|
165
|
+
times(coeff) {
|
|
166
|
+
return new LinExpr(this.terms.map((t) => ({ coeff: t.coeff * coeff, var: t.var })), this.constant * coeff);
|
|
167
|
+
}
|
|
168
|
+
/** Returns -this. */
|
|
169
|
+
neg() {
|
|
170
|
+
return this.times(-1);
|
|
171
|
+
}
|
|
172
|
+
/** Returns a constraint: this <= rhs. */
|
|
173
|
+
leq(rhs) {
|
|
174
|
+
return new Constraint(this, '<=', rhs);
|
|
175
|
+
}
|
|
176
|
+
/** Returns a constraint: this >= rhs. */
|
|
177
|
+
geq(rhs) {
|
|
178
|
+
return new Constraint(this, '>=', rhs);
|
|
179
|
+
}
|
|
180
|
+
/** Returns a constraint: this == rhs. */
|
|
181
|
+
eq(rhs) {
|
|
182
|
+
return new Constraint(this, '=', rhs);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** A decision variable in an optimization model. */
|
|
187
|
+
class Var {
|
|
188
|
+
/** @internal Use Model.numVar(), Model.intVar(), or Model.boolVar() instead. */
|
|
189
|
+
constructor(name, type, lb, ub) {
|
|
190
|
+
this.name = name;
|
|
191
|
+
this.type = type;
|
|
192
|
+
this.lb = lb;
|
|
193
|
+
this.ub = ub;
|
|
194
|
+
}
|
|
195
|
+
toExpr() {
|
|
196
|
+
return new LinExpr([{ coeff: 1, var: this }], 0);
|
|
197
|
+
}
|
|
198
|
+
/** Returns this + other. */
|
|
199
|
+
plus(other) {
|
|
200
|
+
return this.toExpr().plus(other);
|
|
201
|
+
}
|
|
202
|
+
/** Returns this - other. */
|
|
203
|
+
minus(other) {
|
|
204
|
+
return this.toExpr().minus(other);
|
|
205
|
+
}
|
|
206
|
+
/** Returns coeff * this. */
|
|
207
|
+
times(coeff) {
|
|
208
|
+
return new LinExpr([{ coeff, var: this }], 0);
|
|
209
|
+
}
|
|
210
|
+
/** Returns -this. */
|
|
211
|
+
neg() {
|
|
212
|
+
return this.times(-1);
|
|
213
|
+
}
|
|
214
|
+
/** Returns a constraint: this <= rhs. */
|
|
215
|
+
leq(rhs) {
|
|
216
|
+
return this.toExpr().leq(rhs);
|
|
217
|
+
}
|
|
218
|
+
/** Returns a constraint: this >= rhs. */
|
|
219
|
+
geq(rhs) {
|
|
220
|
+
return this.toExpr().geq(rhs);
|
|
221
|
+
}
|
|
222
|
+
/** Returns a constraint: this == rhs. */
|
|
223
|
+
eq(rhs) {
|
|
224
|
+
return this.toExpr().eq(rhs);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** The result of solving a Model. */
|
|
229
|
+
class Solution {
|
|
230
|
+
/** @internal Use Model.solve() to obtain a Solution. */
|
|
231
|
+
constructor(result) {
|
|
232
|
+
this.status = result.status;
|
|
233
|
+
this.objective = result.objective;
|
|
234
|
+
this.values = result.solution ?? new Map();
|
|
235
|
+
}
|
|
236
|
+
/** Returns the value of a variable in the solution, or undefined if not found. */
|
|
237
|
+
getValue(variable) {
|
|
238
|
+
return this.values.get(variable.name);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function toLPFormat(input) {
|
|
243
|
+
const lines = [];
|
|
244
|
+
if (input.sense === 'maximize') {
|
|
245
|
+
lines.push('Maximize');
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
lines.push('Minimize');
|
|
249
|
+
}
|
|
250
|
+
if (input.objective) {
|
|
251
|
+
lines.push(` obj: ${formatExpr(input.objective)}`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
lines.push(' obj: 0');
|
|
255
|
+
}
|
|
256
|
+
lines.push('Subject To');
|
|
257
|
+
let constraintIndex = 0;
|
|
258
|
+
for (const constraint of input.constraints) {
|
|
259
|
+
const name = constraint.name ?? `c${constraintIndex++}`;
|
|
260
|
+
const exprStr = formatExpr(constraint.expr);
|
|
261
|
+
const senseStr = constraint.sense === '=' ? '=' : constraint.sense;
|
|
262
|
+
const rhs = constraint.rhs - constraint.expr.constant;
|
|
263
|
+
lines.push(` ${name}: ${exprStr} ${senseStr} ${formatNumber(rhs)}`);
|
|
264
|
+
}
|
|
265
|
+
const boundsLines = [];
|
|
266
|
+
const generalVars = [];
|
|
267
|
+
const binaryVars = [];
|
|
268
|
+
for (const v of input.variables) {
|
|
269
|
+
if (v.type === 'binary') {
|
|
270
|
+
binaryVars.push(v.name);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
if (v.type === 'integer') {
|
|
274
|
+
generalVars.push(v.name);
|
|
275
|
+
}
|
|
276
|
+
const hasNonDefaultBounds = v.lb !== 0 || v.ub !== Infinity;
|
|
277
|
+
if (hasNonDefaultBounds) {
|
|
278
|
+
if (v.ub === Infinity) {
|
|
279
|
+
boundsLines.push(` ${formatNumber(v.lb)} <= ${v.name}`);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
boundsLines.push(` ${formatNumber(v.lb)} <= ${v.name} <= ${formatNumber(v.ub)}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (boundsLines.length > 0) {
|
|
288
|
+
lines.push('Bounds');
|
|
289
|
+
lines.push(...boundsLines);
|
|
290
|
+
}
|
|
291
|
+
if (generalVars.length > 0) {
|
|
292
|
+
lines.push('General');
|
|
293
|
+
lines.push(` ${generalVars.join(' ')}`);
|
|
294
|
+
}
|
|
295
|
+
if (binaryVars.length > 0) {
|
|
296
|
+
lines.push('Binary');
|
|
297
|
+
lines.push(` ${binaryVars.join(' ')}`);
|
|
298
|
+
}
|
|
299
|
+
lines.push('End');
|
|
300
|
+
return lines.join('\n') + '\n';
|
|
301
|
+
}
|
|
302
|
+
function formatExpr(expr) {
|
|
303
|
+
const consolidated = consolidateTerms(expr);
|
|
304
|
+
if (consolidated.length === 0) {
|
|
305
|
+
return '0';
|
|
306
|
+
}
|
|
307
|
+
const parts = [];
|
|
308
|
+
for (let i = 0; i < consolidated.length; i++) {
|
|
309
|
+
const { coeff, varName } = consolidated[i];
|
|
310
|
+
if (coeff === 0)
|
|
311
|
+
continue;
|
|
312
|
+
if (i === 0) {
|
|
313
|
+
if (coeff === 1) {
|
|
314
|
+
parts.push(varName);
|
|
315
|
+
}
|
|
316
|
+
else if (coeff === -1) {
|
|
317
|
+
parts.push(`- ${varName}`);
|
|
318
|
+
}
|
|
319
|
+
else if (coeff < 0) {
|
|
320
|
+
parts.push(`- ${formatNumber(-coeff)} ${varName}`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
parts.push(`${formatNumber(coeff)} ${varName}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
if (coeff === 1) {
|
|
328
|
+
parts.push(`+ ${varName}`);
|
|
329
|
+
}
|
|
330
|
+
else if (coeff === -1) {
|
|
331
|
+
parts.push(`- ${varName}`);
|
|
332
|
+
}
|
|
333
|
+
else if (coeff < 0) {
|
|
334
|
+
parts.push(`- ${formatNumber(-coeff)} ${varName}`);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
parts.push(`+ ${formatNumber(coeff)} ${varName}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return parts.join(' ') || '0';
|
|
342
|
+
}
|
|
343
|
+
function consolidateTerms(expr) {
|
|
344
|
+
const coeffMap = new Map();
|
|
345
|
+
for (const term of expr.terms) {
|
|
346
|
+
const current = coeffMap.get(term.var.name) ?? 0;
|
|
347
|
+
coeffMap.set(term.var.name, current + term.coeff);
|
|
348
|
+
}
|
|
349
|
+
const result = [];
|
|
350
|
+
for (const [varName, coeff] of coeffMap) {
|
|
351
|
+
if (coeff !== 0) {
|
|
352
|
+
result.push({ coeff, varName });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
function formatNumber(n) {
|
|
358
|
+
if (Number.isInteger(n)) {
|
|
359
|
+
return n.toString();
|
|
360
|
+
}
|
|
361
|
+
return n.toString();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** High-level model builder for optimization problems. */
|
|
365
|
+
class Model {
|
|
366
|
+
constructor() {
|
|
367
|
+
this.variables = [];
|
|
368
|
+
this.constraints = [];
|
|
369
|
+
this.objective = null;
|
|
370
|
+
this.sense = 'minimize';
|
|
371
|
+
this.varCounter = 0;
|
|
372
|
+
}
|
|
373
|
+
/** Creates a continuous variable with the given bounds and optional name. */
|
|
374
|
+
numVar(lb = 0, ub = Infinity, name) {
|
|
375
|
+
const varName = name ?? `x${this.varCounter++}`;
|
|
376
|
+
const v = new Var(varName, 'continuous', lb, ub);
|
|
377
|
+
this.variables.push(v);
|
|
378
|
+
return v;
|
|
379
|
+
}
|
|
380
|
+
/** Creates an integer variable with the given bounds and optional name. */
|
|
381
|
+
intVar(lb = 0, ub = Infinity, name) {
|
|
382
|
+
const varName = name ?? `x${this.varCounter++}`;
|
|
383
|
+
const v = new Var(varName, 'integer', lb, ub);
|
|
384
|
+
this.variables.push(v);
|
|
385
|
+
return v;
|
|
386
|
+
}
|
|
387
|
+
/** Creates a binary (0-1) variable with an optional name. */
|
|
388
|
+
boolVar(name) {
|
|
389
|
+
const varName = name ?? `x${this.varCounter++}`;
|
|
390
|
+
const v = new Var(varName, 'binary', 0, 1);
|
|
391
|
+
this.variables.push(v);
|
|
392
|
+
return v;
|
|
393
|
+
}
|
|
394
|
+
/** Adds a constraint to the model with an optional name. */
|
|
395
|
+
addConstraint(constraint, name) {
|
|
396
|
+
if (name !== undefined) {
|
|
397
|
+
constraint.name = name;
|
|
398
|
+
}
|
|
399
|
+
this.constraints.push(constraint);
|
|
400
|
+
}
|
|
401
|
+
/** Sets the objective to minimize the given expression. */
|
|
402
|
+
minimize(expr) {
|
|
403
|
+
this.objective = expr instanceof Var ? expr.times(1) : expr;
|
|
404
|
+
this.sense = 'minimize';
|
|
405
|
+
}
|
|
406
|
+
/** Sets the objective to maximize the given expression. */
|
|
407
|
+
maximize(expr) {
|
|
408
|
+
this.objective = expr instanceof Var ? expr.times(1) : expr;
|
|
409
|
+
this.sense = 'maximize';
|
|
410
|
+
}
|
|
411
|
+
/** Converts the model to CPLEX LP format. */
|
|
412
|
+
toLPFormat() {
|
|
413
|
+
return toLPFormat({
|
|
414
|
+
objective: this.objective,
|
|
415
|
+
sense: this.sense,
|
|
416
|
+
constraints: this.constraints,
|
|
417
|
+
variables: this.variables,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
/** Solves the model and returns the solution. */
|
|
421
|
+
async solve(options) {
|
|
422
|
+
const lpString = this.toLPFormat();
|
|
423
|
+
const scip = await SCIP$1.create(options);
|
|
424
|
+
try {
|
|
425
|
+
await scip.readProblemFromString(lpString, 'lp');
|
|
426
|
+
const result = await scip.solve();
|
|
427
|
+
return new Solution(result);
|
|
428
|
+
}
|
|
429
|
+
finally {
|
|
430
|
+
scip.free();
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/** Returns the sum of the given variables, expressions, and constants. */
|
|
436
|
+
function sum(...items) {
|
|
437
|
+
let result = new LinExpr([], 0);
|
|
438
|
+
for (const item of items) {
|
|
439
|
+
result = result.plus(item);
|
|
440
|
+
}
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** SCIP solver with Node.js-specific file reading support. */
|
|
445
|
+
class SCIP extends SCIP$1 {
|
|
446
|
+
/** Reads a problem from a file path. The format is inferred from the extension. */
|
|
447
|
+
async readProblem(path) {
|
|
448
|
+
const content = readFileSync(path, 'utf-8');
|
|
449
|
+
const ext = path.split('.').pop() || 'lp';
|
|
450
|
+
await this.readProblemFromString(content, ext);
|
|
451
|
+
}
|
|
452
|
+
static async create(options) {
|
|
453
|
+
const base = await SCIP$1.create(options);
|
|
454
|
+
return Object.setPrototypeOf(base, SCIP.prototype);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export { Constraint, LinExpr, Model, SCIP, Solution, Var, sum };
|
|
459
|
+
//# sourceMappingURL=index.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.node.js","sources":["module.js","solver.js","model/constraint.js","model/expr.js","model/var.js","model/solution.js","model/lp-format.js","model/model.js","model/helpers.js","index.node.js"],"sourcesContent":["/** Loads a fresh SCIP WebAssembly module with the given options. */\nexport async function loadSCIPModule(options) {\n const createModule = await loadSCIPFactory();\n const consoleConfig = options?.console ?? { log: null, error: null };\n const moduleOptions = {\n print: consoleConfig.log ?? (() => { }),\n printErr: consoleConfig.error ?? (() => { }),\n };\n return createModule(moduleOptions);\n}\nasync function loadSCIPFactory() {\n const { default: SCIPModuleFactory } = await import(new URL('../build/scip.js', import.meta.url).href);\n return SCIPModuleFactory;\n}\n//# sourceMappingURL=module.js.map","import { loadSCIPModule } from './module.js';\nconst SCIP_STATUS_MAP = {\n 0: 'unknown',\n 1: 'optimal',\n 2: 'infeasible',\n 3: 'unbounded',\n 4: 'inforunbd',\n 5: 'timelimit',\n 6: 'nodelimit',\n 7: 'stallnodelimit',\n 8: 'gaplimit',\n 9: 'sollimit',\n 10: 'bestsollimit',\n 11: 'restartlimit',\n};\n/** Low-level wrapper around the SCIP optimization solver. */\nexport class SCIP {\n constructor(module, scipPtr) {\n this.freed = false;\n this.module = module;\n this.scipPtr = scipPtr;\n }\n /** Creates a new SCIP solver instance. */\n static async create(options) {\n const module = await loadSCIPModule(options);\n const scipPtrPtr = module._malloc(4);\n try {\n module.ccall('SCIPcreate', 'number', ['number'], [scipPtrPtr]);\n const scipPtr = module.getValue(scipPtrPtr, 'i32');\n if (scipPtr === 0) {\n throw new Error('SCIPcreate failed to create instance');\n }\n module.ccall('SCIPincludeDefaultPlugins', 'number', ['number'], [scipPtr]);\n return new SCIP(module, scipPtr);\n }\n finally {\n module._free(scipPtrPtr);\n }\n }\n /** Reads a problem from a string in the given format (e.g., 'lp', 'mps'). */\n async readProblemFromString(content, format) {\n this.ensureNotFreed();\n const filename = `/tmp/problem.${format}`;\n this.module.FS.writeFile(filename, content);\n try {\n this.module.ccall('SCIPreadProb', 'number', ['number', 'string', 'string'], [this.scipPtr, filename, format]);\n }\n finally {\n try {\n this.module.FS.unlink(filename);\n }\n catch {\n // Ignore cleanup errors\n }\n }\n }\n /** Solves the loaded problem and returns the result. */\n async solve() {\n this.ensureNotFreed();\n this.module.ccall('SCIPsolve', 'number', ['number'], [this.scipPtr]);\n const statusCode = this.module.ccall('SCIPgetStatus', 'number', ['number'], [this.scipPtr]);\n const status = SCIP_STATUS_MAP[statusCode] ?? 'unknown';\n const result = { status };\n if (status === 'optimal' || status === 'timelimit' || status === 'gaplimit' ||\n status === 'sollimit' || status === 'bestsollimit') {\n const solPtr = this.module.ccall('SCIPgetBestSol', 'number', ['number'], [this.scipPtr]);\n if (solPtr !== 0) {\n result.objective = this.module.ccall('SCIPgetSolOrigObj', 'number', ['number', 'number'], [this.scipPtr, solPtr]);\n result.solution = this.extractSolution(solPtr);\n }\n }\n return result;\n }\n extractSolution(solPtr) {\n const solution = new Map();\n const nVars = this.module.ccall('SCIPgetNOrigVars', 'number', ['number'], [this.scipPtr]);\n const varsPtr = this.module.ccall('SCIPgetOrigVars', 'number', ['number'], [this.scipPtr]);\n for (let i = 0; i < nVars; i++) {\n const varPtr = this.module.getValue(varsPtr + i * 4, 'i32');\n const namePtr = this.module.ccall('SCIPvarGetName', 'number', ['number'], [varPtr]);\n const name = this.module.UTF8ToString(namePtr);\n const value = this.module.ccall('SCIPgetSolVal', 'number', ['number', 'number', 'number'], [this.scipPtr, solPtr, varPtr]);\n solution.set(name, value);\n }\n return solution;\n }\n /** Frees the SCIP instance. Safe to call multiple times. */\n free() {\n if (this.freed) {\n return;\n }\n const scipPtrPtr = this.module._malloc(4);\n try {\n this.module.setValue(scipPtrPtr, this.scipPtr, 'i32');\n this.module.ccall('SCIPfree', 'number', ['number'], [scipPtrPtr]);\n }\n finally {\n this.module._free(scipPtrPtr);\n }\n this.freed = true;\n }\n ensureNotFreed() {\n if (this.freed) {\n throw new Error('SCIP instance has been freed');\n }\n }\n}\n//# sourceMappingURL=solver.js.map","/** A linear constraint: expr sense rhs (e.g., x + y <= 10). */\nexport class Constraint {\n /** @internal Use leq(), geq(), or eq() methods on expressions instead. */\n constructor(expr, sense, rhs, name) {\n this.expr = expr;\n this.sense = sense;\n this.rhs = rhs;\n this.name = name;\n }\n}\n//# sourceMappingURL=constraint.js.map","import { Constraint } from './constraint.js';\n/** A linear expression: sum of terms plus a constant. */\nexport class LinExpr {\n /** @internal Use variable arithmetic methods (plus, minus, times) instead. */\n constructor(terms, constant) {\n this.terms = terms;\n this.constant = constant;\n }\n /** Returns this + other. */\n plus(other) {\n if (typeof other === 'number') {\n return new LinExpr(this.terms, this.constant + other);\n }\n if (other instanceof LinExpr) {\n return new LinExpr([...this.terms, ...other.terms], this.constant + other.constant);\n }\n return new LinExpr([...this.terms, { coeff: 1, var: other }], this.constant);\n }\n /** Returns this - other. */\n minus(other) {\n if (typeof other === 'number') {\n return new LinExpr(this.terms, this.constant - other);\n }\n if (other instanceof LinExpr) {\n const negatedTerms = other.terms.map((t) => ({ coeff: -t.coeff, var: t.var }));\n return new LinExpr([...this.terms, ...negatedTerms], this.constant - other.constant);\n }\n return new LinExpr([...this.terms, { coeff: -1, var: other }], this.constant);\n }\n /** Returns coeff * this. */\n times(coeff) {\n return new LinExpr(this.terms.map((t) => ({ coeff: t.coeff * coeff, var: t.var })), this.constant * coeff);\n }\n /** Returns -this. */\n neg() {\n return this.times(-1);\n }\n /** Returns a constraint: this <= rhs. */\n leq(rhs) {\n return new Constraint(this, '<=', rhs);\n }\n /** Returns a constraint: this >= rhs. */\n geq(rhs) {\n return new Constraint(this, '>=', rhs);\n }\n /** Returns a constraint: this == rhs. */\n eq(rhs) {\n return new Constraint(this, '=', rhs);\n }\n}\n//# sourceMappingURL=expr.js.map","import { LinExpr } from './expr.js';\n/** A decision variable in an optimization model. */\nexport class Var {\n /** @internal Use Model.numVar(), Model.intVar(), or Model.boolVar() instead. */\n constructor(name, type, lb, ub) {\n this.name = name;\n this.type = type;\n this.lb = lb;\n this.ub = ub;\n }\n toExpr() {\n return new LinExpr([{ coeff: 1, var: this }], 0);\n }\n /** Returns this + other. */\n plus(other) {\n return this.toExpr().plus(other);\n }\n /** Returns this - other. */\n minus(other) {\n return this.toExpr().minus(other);\n }\n /** Returns coeff * this. */\n times(coeff) {\n return new LinExpr([{ coeff, var: this }], 0);\n }\n /** Returns -this. */\n neg() {\n return this.times(-1);\n }\n /** Returns a constraint: this <= rhs. */\n leq(rhs) {\n return this.toExpr().leq(rhs);\n }\n /** Returns a constraint: this >= rhs. */\n geq(rhs) {\n return this.toExpr().geq(rhs);\n }\n /** Returns a constraint: this == rhs. */\n eq(rhs) {\n return this.toExpr().eq(rhs);\n }\n}\n//# sourceMappingURL=var.js.map","/** The result of solving a Model. */\nexport class Solution {\n /** @internal Use Model.solve() to obtain a Solution. */\n constructor(result) {\n this.status = result.status;\n this.objective = result.objective;\n this.values = result.solution ?? new Map();\n }\n /** Returns the value of a variable in the solution, or undefined if not found. */\n getValue(variable) {\n return this.values.get(variable.name);\n }\n}\n//# sourceMappingURL=solution.js.map","export function toLPFormat(input) {\n const lines = [];\n if (input.sense === 'maximize') {\n lines.push('Maximize');\n }\n else {\n lines.push('Minimize');\n }\n if (input.objective) {\n lines.push(` obj: ${formatExpr(input.objective)}`);\n }\n else {\n lines.push(' obj: 0');\n }\n lines.push('Subject To');\n let constraintIndex = 0;\n for (const constraint of input.constraints) {\n const name = constraint.name ?? `c${constraintIndex++}`;\n const exprStr = formatExpr(constraint.expr);\n const senseStr = constraint.sense === '=' ? '=' : constraint.sense;\n const rhs = constraint.rhs - constraint.expr.constant;\n lines.push(` ${name}: ${exprStr} ${senseStr} ${formatNumber(rhs)}`);\n }\n const boundsLines = [];\n const generalVars = [];\n const binaryVars = [];\n for (const v of input.variables) {\n if (v.type === 'binary') {\n binaryVars.push(v.name);\n }\n else {\n if (v.type === 'integer') {\n generalVars.push(v.name);\n }\n const hasNonDefaultBounds = v.lb !== 0 || v.ub !== Infinity;\n if (hasNonDefaultBounds) {\n if (v.ub === Infinity) {\n boundsLines.push(` ${formatNumber(v.lb)} <= ${v.name}`);\n }\n else {\n boundsLines.push(` ${formatNumber(v.lb)} <= ${v.name} <= ${formatNumber(v.ub)}`);\n }\n }\n }\n }\n if (boundsLines.length > 0) {\n lines.push('Bounds');\n lines.push(...boundsLines);\n }\n if (generalVars.length > 0) {\n lines.push('General');\n lines.push(` ${generalVars.join(' ')}`);\n }\n if (binaryVars.length > 0) {\n lines.push('Binary');\n lines.push(` ${binaryVars.join(' ')}`);\n }\n lines.push('End');\n return lines.join('\\n') + '\\n';\n}\nfunction formatExpr(expr) {\n const consolidated = consolidateTerms(expr);\n if (consolidated.length === 0) {\n return '0';\n }\n const parts = [];\n for (let i = 0; i < consolidated.length; i++) {\n const { coeff, varName } = consolidated[i];\n if (coeff === 0)\n continue;\n if (i === 0) {\n if (coeff === 1) {\n parts.push(varName);\n }\n else if (coeff === -1) {\n parts.push(`- ${varName}`);\n }\n else if (coeff < 0) {\n parts.push(`- ${formatNumber(-coeff)} ${varName}`);\n }\n else {\n parts.push(`${formatNumber(coeff)} ${varName}`);\n }\n }\n else {\n if (coeff === 1) {\n parts.push(`+ ${varName}`);\n }\n else if (coeff === -1) {\n parts.push(`- ${varName}`);\n }\n else if (coeff < 0) {\n parts.push(`- ${formatNumber(-coeff)} ${varName}`);\n }\n else {\n parts.push(`+ ${formatNumber(coeff)} ${varName}`);\n }\n }\n }\n return parts.join(' ') || '0';\n}\nfunction consolidateTerms(expr) {\n const coeffMap = new Map();\n for (const term of expr.terms) {\n const current = coeffMap.get(term.var.name) ?? 0;\n coeffMap.set(term.var.name, current + term.coeff);\n }\n const result = [];\n for (const [varName, coeff] of coeffMap) {\n if (coeff !== 0) {\n result.push({ coeff, varName });\n }\n }\n return result;\n}\nfunction formatNumber(n) {\n if (Number.isInteger(n)) {\n return n.toString();\n }\n return n.toString();\n}\n//# sourceMappingURL=lp-format.js.map","import { SCIP as BaseSCIP } from '../solver.js';\nimport { Var } from './var.js';\nimport { Solution } from './solution.js';\nimport { toLPFormat } from './lp-format.js';\n/** High-level model builder for optimization problems. */\nexport class Model {\n constructor() {\n this.variables = [];\n this.constraints = [];\n this.objective = null;\n this.sense = 'minimize';\n this.varCounter = 0;\n }\n /** Creates a continuous variable with the given bounds and optional name. */\n numVar(lb = 0, ub = Infinity, name) {\n const varName = name ?? `x${this.varCounter++}`;\n const v = new Var(varName, 'continuous', lb, ub);\n this.variables.push(v);\n return v;\n }\n /** Creates an integer variable with the given bounds and optional name. */\n intVar(lb = 0, ub = Infinity, name) {\n const varName = name ?? `x${this.varCounter++}`;\n const v = new Var(varName, 'integer', lb, ub);\n this.variables.push(v);\n return v;\n }\n /** Creates a binary (0-1) variable with an optional name. */\n boolVar(name) {\n const varName = name ?? `x${this.varCounter++}`;\n const v = new Var(varName, 'binary', 0, 1);\n this.variables.push(v);\n return v;\n }\n /** Adds a constraint to the model with an optional name. */\n addConstraint(constraint, name) {\n if (name !== undefined) {\n constraint.name = name;\n }\n this.constraints.push(constraint);\n }\n /** Sets the objective to minimize the given expression. */\n minimize(expr) {\n this.objective = expr instanceof Var ? expr.times(1) : expr;\n this.sense = 'minimize';\n }\n /** Sets the objective to maximize the given expression. */\n maximize(expr) {\n this.objective = expr instanceof Var ? expr.times(1) : expr;\n this.sense = 'maximize';\n }\n /** Converts the model to CPLEX LP format. */\n toLPFormat() {\n return toLPFormat({\n objective: this.objective,\n sense: this.sense,\n constraints: this.constraints,\n variables: this.variables,\n });\n }\n /** Solves the model and returns the solution. */\n async solve(options) {\n const lpString = this.toLPFormat();\n const scip = await BaseSCIP.create(options);\n try {\n await scip.readProblemFromString(lpString, 'lp');\n const result = await scip.solve();\n return new Solution(result);\n }\n finally {\n scip.free();\n }\n }\n}\n//# sourceMappingURL=model.js.map","import { LinExpr } from './expr.js';\n/** Returns the sum of the given variables, expressions, and constants. */\nexport function sum(...items) {\n let result = new LinExpr([], 0);\n for (const item of items) {\n result = result.plus(item);\n }\n return result;\n}\n//# sourceMappingURL=helpers.js.map","import { readFileSync } from 'fs';\nimport { SCIP as BaseSCIP } from './solver.js';\nexport { Model, Var, LinExpr, Constraint, Solution, sum, } from './model/index.js';\n/** SCIP solver with Node.js-specific file reading support. */\nexport class SCIP extends BaseSCIP {\n /** Reads a problem from a file path. The format is inferred from the extension. */\n async readProblem(path) {\n const content = readFileSync(path, 'utf-8');\n const ext = path.split('.').pop() || 'lp';\n await this.readProblemFromString(content, ext);\n }\n static async create(options) {\n const base = await BaseSCIP.create(options);\n return Object.setPrototypeOf(base, SCIP.prototype);\n }\n}\n//# sourceMappingURL=index.node.js.map"],"names":["BaseSCIP"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Sense } from './types.js';
|
|
2
|
+
import type { LinExpr } from './expr.js';
|
|
3
|
+
/** A linear constraint: expr sense rhs (e.g., x + y <= 10). */
|
|
4
|
+
export declare class Constraint {
|
|
5
|
+
readonly expr: LinExpr;
|
|
6
|
+
readonly sense: Sense;
|
|
7
|
+
readonly rhs: number;
|
|
8
|
+
name?: string;
|
|
9
|
+
/** @internal Use leq(), geq(), or eq() methods on expressions instead. */
|
|
10
|
+
constructor(expr: LinExpr, sense: Sense, rhs: number, name?: string);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=constraint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraint.d.ts","sourceRoot":"","sources":["../../src/model/constraint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,+DAA+D;AAC/D,qBAAa,UAAU;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,0EAA0E;gBAC9D,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAMpE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** A linear constraint: expr sense rhs (e.g., x + y <= 10). */
|
|
2
|
+
export class Constraint {
|
|
3
|
+
/** @internal Use leq(), geq(), or eq() methods on expressions instead. */
|
|
4
|
+
constructor(expr, sense, rhs, name) {
|
|
5
|
+
this.expr = expr;
|
|
6
|
+
this.sense = sense;
|
|
7
|
+
this.rhs = rhs;
|
|
8
|
+
this.name = name;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=constraint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraint.js","sourceRoot":"","sources":["../../src/model/constraint.ts"],"names":[],"mappings":"AAGA,+DAA+D;AAC/D,MAAM,OAAO,UAAU;IAMrB,0EAA0E;IAC1E,YAAY,IAAa,EAAE,KAAY,EAAE,GAAW,EAAE,IAAa;QACjE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Term } from './types.js';
|
|
2
|
+
import type { Var } from './var.js';
|
|
3
|
+
import { Constraint } from './constraint.js';
|
|
4
|
+
/** A linear expression: sum of terms plus a constant. */
|
|
5
|
+
export declare class LinExpr {
|
|
6
|
+
readonly terms: Term[];
|
|
7
|
+
readonly constant: number;
|
|
8
|
+
/** @internal Use variable arithmetic methods (plus, minus, times) instead. */
|
|
9
|
+
constructor(terms: Term[], constant: number);
|
|
10
|
+
/** Returns this + other. */
|
|
11
|
+
plus(other: Var | LinExpr | number): LinExpr;
|
|
12
|
+
/** Returns this - other. */
|
|
13
|
+
minus(other: Var | LinExpr | number): LinExpr;
|
|
14
|
+
/** Returns coeff * this. */
|
|
15
|
+
times(coeff: number): LinExpr;
|
|
16
|
+
/** Returns -this. */
|
|
17
|
+
neg(): LinExpr;
|
|
18
|
+
/** Returns a constraint: this <= rhs. */
|
|
19
|
+
leq(rhs: number): Constraint;
|
|
20
|
+
/** Returns a constraint: this >= rhs. */
|
|
21
|
+
geq(rhs: number): Constraint;
|
|
22
|
+
/** Returns a constraint: this == rhs. */
|
|
23
|
+
eq(rhs: number): Constraint;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=expr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expr.d.ts","sourceRoot":"","sources":["../../src/model/expr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,yDAAyD;AACzD,qBAAa,OAAO;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,8EAA8E;gBAClE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM;IAK3C,4BAA4B;IAC5B,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO;IAgB5C,4BAA4B;IAC5B,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO;IAiB7C,4BAA4B;IAC5B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAO7B,qBAAqB;IACrB,GAAG,IAAI,OAAO;IAId,yCAAyC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAI5B,yCAAyC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAI5B,yCAAyC;IACzC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;CAG5B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Constraint } from './constraint.js';
|
|
2
|
+
/** A linear expression: sum of terms plus a constant. */
|
|
3
|
+
export class LinExpr {
|
|
4
|
+
/** @internal Use variable arithmetic methods (plus, minus, times) instead. */
|
|
5
|
+
constructor(terms, constant) {
|
|
6
|
+
this.terms = terms;
|
|
7
|
+
this.constant = constant;
|
|
8
|
+
}
|
|
9
|
+
/** Returns this + other. */
|
|
10
|
+
plus(other) {
|
|
11
|
+
if (typeof other === 'number') {
|
|
12
|
+
return new LinExpr(this.terms, this.constant + other);
|
|
13
|
+
}
|
|
14
|
+
if (other instanceof LinExpr) {
|
|
15
|
+
return new LinExpr([...this.terms, ...other.terms], this.constant + other.constant);
|
|
16
|
+
}
|
|
17
|
+
return new LinExpr([...this.terms, { coeff: 1, var: other }], this.constant);
|
|
18
|
+
}
|
|
19
|
+
/** Returns this - other. */
|
|
20
|
+
minus(other) {
|
|
21
|
+
if (typeof other === 'number') {
|
|
22
|
+
return new LinExpr(this.terms, this.constant - other);
|
|
23
|
+
}
|
|
24
|
+
if (other instanceof LinExpr) {
|
|
25
|
+
const negatedTerms = other.terms.map((t) => ({ coeff: -t.coeff, var: t.var }));
|
|
26
|
+
return new LinExpr([...this.terms, ...negatedTerms], this.constant - other.constant);
|
|
27
|
+
}
|
|
28
|
+
return new LinExpr([...this.terms, { coeff: -1, var: other }], this.constant);
|
|
29
|
+
}
|
|
30
|
+
/** Returns coeff * this. */
|
|
31
|
+
times(coeff) {
|
|
32
|
+
return new LinExpr(this.terms.map((t) => ({ coeff: t.coeff * coeff, var: t.var })), this.constant * coeff);
|
|
33
|
+
}
|
|
34
|
+
/** Returns -this. */
|
|
35
|
+
neg() {
|
|
36
|
+
return this.times(-1);
|
|
37
|
+
}
|
|
38
|
+
/** Returns a constraint: this <= rhs. */
|
|
39
|
+
leq(rhs) {
|
|
40
|
+
return new Constraint(this, '<=', rhs);
|
|
41
|
+
}
|
|
42
|
+
/** Returns a constraint: this >= rhs. */
|
|
43
|
+
geq(rhs) {
|
|
44
|
+
return new Constraint(this, '>=', rhs);
|
|
45
|
+
}
|
|
46
|
+
/** Returns a constraint: this == rhs. */
|
|
47
|
+
eq(rhs) {
|
|
48
|
+
return new Constraint(this, '=', rhs);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=expr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expr.js","sourceRoot":"","sources":["../../src/model/expr.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,yDAAyD;AACzD,MAAM,OAAO,OAAO;IAIlB,8EAA8E;IAC9E,YAAY,KAAa,EAAE,QAAgB;QACzC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC,KAA6B;QAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;YAC7B,OAAO,IAAI,OAAO,CAChB,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,EAC/B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAC/B,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,OAAO,CAChB,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EACzC,IAAI,CAAC,QAAQ,CACd,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,KAAK,CAAC,KAA6B;QACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;YAC7B,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC/E,OAAO,IAAI,OAAO,CAChB,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,YAAY,CAAC,EAChC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAC/B,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,OAAO,CAChB,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAC1C,IAAI,CAAC,QAAQ,CACd,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,KAAK,CAAC,KAAa;QACjB,OAAO,IAAI,OAAO,CAChB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAC/D,IAAI,CAAC,QAAQ,GAAG,KAAK,CACtB,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,GAAG;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,yCAAyC;IACzC,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,yCAAyC;IACzC,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,yCAAyC;IACzC,EAAE,CAAC,GAAW;QACZ,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/model/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,0EAA0E;AAC1E,wBAAgB,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAMjE"}
|