cpsat-js 1.1.0 → 1.3.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.md +76 -1
- package/build/portable/cpsat.mjs +1 -1
- package/build/portable/cpsat.wasm +0 -0
- package/build/threaded/cpsat.mjs +1 -1
- package/build/threaded/cpsat.wasm +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model/cp-model.d.ts +23 -0
- package/dist/model/cp-model.d.ts.map +1 -1
- package/dist/model/cp-model.js +37 -1
- package/dist/model/cp-model.js.map +1 -1
- package/dist/solver/cp-solver.d.ts +50 -1
- package/dist/solver/cp-solver.d.ts.map +1 -1
- package/dist/solver/cp-solver.js +38 -1
- package/dist/solver/cp-solver.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,12 +7,17 @@ export interface CpSolverOptions {
|
|
|
7
7
|
locateFile?: (path: string) => string;
|
|
8
8
|
}
|
|
9
9
|
interface CpSatModule {
|
|
10
|
-
_solve(modelPtr: number, modelLen: number, paramsPtr: number, paramsLen: number): number;
|
|
10
|
+
_solve(modelPtr: number, modelLen: number, paramsPtr: number, paramsLen: number, observe: number): number;
|
|
11
11
|
_get_result_ptr(): number;
|
|
12
12
|
_free_result(): void;
|
|
13
|
+
_solution_count(): number;
|
|
14
|
+
_solution_ptr(index: number): number;
|
|
15
|
+
_solution_len(index: number): number;
|
|
13
16
|
_malloc(size: number): number;
|
|
14
17
|
_free(ptr: number): void;
|
|
15
18
|
HEAPU8: Uint8Array;
|
|
19
|
+
/** Where the C++ observer reaches for a live callback. Set only during a solve. */
|
|
20
|
+
__cpsatOnSolution?: (bytes: Uint8Array) => void;
|
|
16
21
|
}
|
|
17
22
|
export type WasmFactory = (options?: Record<string, unknown>) => Promise<CpSatModule>;
|
|
18
23
|
/**
|
|
@@ -36,6 +41,40 @@ export interface SolverParams {
|
|
|
36
41
|
* than 1 on real models. Use 1 or >= 6, never in between.
|
|
37
42
|
*/
|
|
38
43
|
numWorkers?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Report every solution rather than stopping at the first.
|
|
46
|
+
*
|
|
47
|
+
* **Only meaningful on a model with no objective.** CP-SAT's own wording is "whether
|
|
48
|
+
* we enumerate all solutions of a problem without objective"; with an objective the
|
|
49
|
+
* search reports improving solutions instead, and this does nothing for you.
|
|
50
|
+
*
|
|
51
|
+
* Combined with `onSolution` this is what streams a complete solution set as the
|
|
52
|
+
* search finds it. The solutions arrive in whatever order the search happens on —
|
|
53
|
+
* there is no objective, so there is no ordering — and OR-Tools warns against reading
|
|
54
|
+
* anything into it beyond completeness.
|
|
55
|
+
*
|
|
56
|
+
* Setting this also disables the presolve reductions that can remove feasible
|
|
57
|
+
* solutions, which is the same effect as `keep_all_feasible_solutions_in_presolve`.
|
|
58
|
+
*/
|
|
59
|
+
enumerateAllSolutions?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Called for each improving solution the search finds.
|
|
62
|
+
*
|
|
63
|
+
* Purely observational: the return value is ignored and nothing here can steer or
|
|
64
|
+
* stop the search. Use `maxTimeInSeconds` to bound it.
|
|
65
|
+
*
|
|
66
|
+
* **When the calls arrive depends on `numWorkers`.** At 1 worker CP-SAT solves on
|
|
67
|
+
* the calling thread, so these are live — they interleave with the search, and
|
|
68
|
+
* `solve()` has not returned yet. Above 1 worker the search runs on threads that
|
|
69
|
+
* cannot enter JS, so incumbents are recorded and replayed in order just before
|
|
70
|
+
* `solve()` returns. `live` on each solution says which happened. The sequence and
|
|
71
|
+
* its contents are the same either way; only the timing differs.
|
|
72
|
+
*
|
|
73
|
+
* At 1 worker the handler runs inside the solver, holding a lock: keep it quick,
|
|
74
|
+
* and do not call back into the solver from it. Post the solution somewhere and
|
|
75
|
+
* return.
|
|
76
|
+
*/
|
|
77
|
+
onSolution?: (solution: CpSolverSolution) => void;
|
|
39
78
|
}
|
|
40
79
|
export interface CpSolverResult {
|
|
41
80
|
status: CpSolverStatus;
|
|
@@ -47,6 +86,16 @@ export interface CpSolverResult {
|
|
|
47
86
|
/** Raw response proto */
|
|
48
87
|
response: CpSolverResponse;
|
|
49
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* One improving solution seen during the search.
|
|
91
|
+
*
|
|
92
|
+
* The same shape as a final result — including `value()` — so an incumbent and an
|
|
93
|
+
* answer can be read by the same code.
|
|
94
|
+
*/
|
|
95
|
+
export interface CpSolverSolution extends CpSolverResult {
|
|
96
|
+
/** Delivered mid-solve (1 worker), or replayed just before solve() returned. */
|
|
97
|
+
live: boolean;
|
|
98
|
+
}
|
|
50
99
|
/**
|
|
51
100
|
* Loads the WASM module and solves CP-SAT models.
|
|
52
101
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cp-solver.d.ts","sourceRoot":"","sources":["../../src/solver/cp-solver.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,cAAc,EACd,KAAK,gBAAgB,EACtB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED,UAAU,WAAW;IACnB,MAAM,
|
|
1
|
+
{"version":3,"file":"cp-solver.d.ts","sourceRoot":"","sources":["../../src/solver/cp-solver.ts"],"names":[],"mappings":"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"}
|
package/dist/solver/cp-solver.js
CHANGED
|
@@ -9,6 +9,19 @@ export function setGlueLoader(loader, threaded) {
|
|
|
9
9
|
glueLoader = loader;
|
|
10
10
|
glueIsThreaded = threaded;
|
|
11
11
|
}
|
|
12
|
+
/** Build the caller-facing view of a response. Shared by results and incumbents. */
|
|
13
|
+
function readResponse(response) {
|
|
14
|
+
return {
|
|
15
|
+
status: response.status,
|
|
16
|
+
objectiveValue: response.objectiveValue,
|
|
17
|
+
bestObjectiveBound: response.bestObjectiveBound,
|
|
18
|
+
wallTime: response.wallTime,
|
|
19
|
+
value(variable) {
|
|
20
|
+
return Number(response.solution[variable.index]);
|
|
21
|
+
},
|
|
22
|
+
response,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
12
25
|
/**
|
|
13
26
|
* Loads the WASM module and solves CP-SAT models.
|
|
14
27
|
*
|
|
@@ -45,6 +58,9 @@ export class CpSolver {
|
|
|
45
58
|
if (params?.numWorkers !== undefined) {
|
|
46
59
|
satParams.numWorkers = params.numWorkers;
|
|
47
60
|
}
|
|
61
|
+
if (params?.enumerateAllSolutions !== undefined) {
|
|
62
|
+
satParams.enumerateAllSolutions = params.enumerateAllSolutions;
|
|
63
|
+
}
|
|
48
64
|
// The portable build has no threads. Clamp to 1 rather than to some lower count:
|
|
49
65
|
// anything in 2..5 selects a degraded portfolio and is slower than a single worker.
|
|
50
66
|
if (!glueIsThreaded) {
|
|
@@ -57,13 +73,34 @@ export class CpSolver {
|
|
|
57
73
|
// Allocate WASM heap memory for params
|
|
58
74
|
const paramsPtr = this.module._malloc(paramsBytes.length);
|
|
59
75
|
this.module.HEAPU8.set(paramsBytes, paramsPtr);
|
|
76
|
+
const onSolution = params?.onSolution;
|
|
77
|
+
if (onSolution) {
|
|
78
|
+
this.module.__cpsatOnSolution = (bytes) => {
|
|
79
|
+
onSolution({ ...readResponse(fromBinary(CpSolverResponseSchema, bytes)), live: true });
|
|
80
|
+
};
|
|
81
|
+
}
|
|
60
82
|
let resultLen;
|
|
61
83
|
try {
|
|
62
|
-
resultLen = this.module._solve(modelPtr, modelBytes.length, paramsPtr, paramsBytes.length);
|
|
84
|
+
resultLen = this.module._solve(modelPtr, modelBytes.length, paramsPtr, paramsBytes.length, onSolution ? 1 : 0);
|
|
63
85
|
}
|
|
64
86
|
finally {
|
|
65
87
|
this.module._free(modelPtr);
|
|
66
88
|
this.module._free(paramsPtr);
|
|
89
|
+
delete this.module.__cpsatOnSolution;
|
|
90
|
+
}
|
|
91
|
+
// Incumbents the observer could only record, because it ran on a thread that
|
|
92
|
+
// cannot enter JS. Drained unconditionally: a live solve recorded nothing, so the
|
|
93
|
+
// count is zero and this does nothing. That way the 1-vs-many rule lives in one
|
|
94
|
+
// place — the C++ observer — and is never restated here to drift out of step.
|
|
95
|
+
if (onSolution) {
|
|
96
|
+
const recorded = this.module._solution_count();
|
|
97
|
+
for (let i = 0; i < recorded; i++) {
|
|
98
|
+
const ptr = this.module._solution_ptr(i);
|
|
99
|
+
const len = this.module._solution_len(i);
|
|
100
|
+
// Re-read HEAPU8 each time: growing the heap replaces the buffer.
|
|
101
|
+
const bytes = this.module.HEAPU8.slice(ptr, ptr + len);
|
|
102
|
+
onSolution({ ...readResponse(fromBinary(CpSolverResponseSchema, bytes)), live: false });
|
|
103
|
+
}
|
|
67
104
|
}
|
|
68
105
|
// Read result from WASM memory
|
|
69
106
|
const resultPtr = this.module._get_result_ptr();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cp-solver.js","sourceRoot":"","sources":["../../src/solver/cp-solver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,cAAc,GAEf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,cAAc,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"cp-solver.js","sourceRoot":"","sources":["../../src/solver/cp-solver.ts"],"names":[],"mappings":"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"}
|