Solve complex optimization models from TypeScript with Google OR-Tools running as multithreaded WebAssembly.
Used in PragmaPlanner.
Run the local test site:
npm install
npm run devInstall from npm:
npm install or-tools-wasmImport the solver API you need from its subpath:
import { CpSat } from 'or-tools-wasm/cp-sat';Public solver APIs live under solver-scoped subpaths:
import { CpModel, CpSolver } from 'or-tools-wasm/cp-sat';
import { RoutingIndexManager, RoutingModel } from 'or-tools-wasm/routing';
import { MPSolver } from 'or-tools-wasm/mp-solver';
import { MathOpt } from 'or-tools-wasm/mathopt';
import { Pdlp } from 'or-tools-wasm/pdlp';
import { KnapsackSolver } from 'or-tools-wasm/knapsack';
import { SimpleMaxFlow } from 'or-tools-wasm/network-flow';
import { SetCoverModel } from 'or-tools-wasm/set-cover';
import { RcpspModelBuilder } from 'or-tools-wasm/rcpsp';Create or serialize an OR-Tools proto model, validate it, then solve it:
const model = {
name: 'choose_one',
variables: [
{ name: 'x', domain: [0, 1] },
{ name: 'y', domain: [0, 1] },
],
constraints: [
{
name: 'exactly_one',
linear: {
vars: [0, 1],
coeffs: [1, 1],
domain: [1, 1],
},
},
],
objective: {
vars: [0, 1],
coeffs: [1, 2],
},
};
const modelBytes = await CpSat.createModel(model);
const validation = await CpSat.validate(modelBytes);
if (!validation.ok) {
throw new Error(validation.message);
}
const result = await CpSat.solve(modelBytes, {
numSearchWorkers: 1,
});
console.log(result.response);| OR-Tools surface | or-tools-wasm | Description |
|---|---|---|
| CP-SAT | ✅ | Constraint and integer optimization for Boolean, integer, scheduling, and logical models. |
| Routing | ✅ | Vehicle routing, TSP, pickup-delivery, capacity, dimension, and time-window search. |
| MPSolver API | ✅ | Linear and mixed-integer programming wrapper; this package includes GLOP LP, CLP LP, GLPK LP/MIP, SCIP MIP, CBC MIP, BOP MIP, Knapsack MIP, and SAT MIP backends. |
| MathOpt API | ✅ | Unified modeling and solve API; this package includes GLOP, GLPK, GSCIP, CP-SAT, and PDLP backends. |
| GLOP | ✅ | Google's simplex linear programming solver. |
| PDLP | ✅ | First-order LP and convex diagonal quadratic solver for very large models. |
| SAT integer programming | ✅ | CP-SAT-backed integer programming backend for pure integer linear models. |
| CLP | ✅ | COIN-OR linear programming backend. |
| GLPK | ✅ | GNU linear and mixed-integer programming backend. |
| SCIP / GSCIP | ✅ | SCIP-based mixed-integer backend through MPSolver and MathOpt. |
| CBC | ✅ | COIN-OR branch-and-cut mixed-integer programming backend through MPSolver. |
| BOP | ✅ | Boolean/integer optimization backend through MPSolver. |
| Knapsack | ✅ | Dedicated 0-1 and multi-dimensional knapsack solver, plus the MPSolver Knapsack backend. |
| Network flow algorithms | ✅ | Dedicated max-flow, min-cost-flow, and linear-sum assignment graph algorithms. |
| Assignment algorithms | ✅ | Linear-sum assignment through the dedicated Network Flow API. |
| Set cover | ✅ | Dedicated weighted set cover model, invariant, and heuristic search API. |
| RCPSP | ✅ | CP-SAT-backed resource-constrained project scheduling model, parser, and visual scheduling surface. |
| Linear Solver ModelBuilder | Python-like linear_solver.model_builder API for ergonomic LP/MIP modeling, import/export helpers, and backend solve helpers. |
|
| MathOpt incremental/callback APIs | ✅ | Incremental solving is exposed for MathOpt models with tracked updates for common LP/MIP model edits, rejected-update fallback, repeated LP updates, and GSCIP incremental message logging. Indicator constraints, message callbacks, solve interrupters, common solve parameters, typed model solve parameters with solve filters, Python-style solve-result accessors including ray/basis helpers for real solve results, removeNames duplicate-name solving, and typed backend parameters for GSCIP, GLOP, CP-SAT, PDLP, and GLPK are exposed. Python-only context managers and constructed result parser/proto-object helpers are outside the current TypeScript contract. |
Unchecked rows are planned OR-Tools targets that are not exposed by this package yet. Commercial and large third-party native backends such as Gurobi, CPLEX, XPRESS, HiGHS, OSQP, ECOS, and SCS are not planned.
The TypeScript API mirrors the public OR-Tools API shape where it maps cleanly
to WebAssembly. CP-SAT exposes both a Python-like high-level builder and the
proto-first CpSat API, routing exposes the familiar RoutingIndexManager and
RoutingModel APIs, MPSolver exposes the pywraplp-style solver API, and
MathOpt exposes a TypeScript model builder.
The worker script and WebAssembly files are emitted automatically from package
imports, with no manual copying into public/ or static/ required.
npm run test:fixtures is the full fixture matrix. It runs the shared solver
cases through Vite, Webpack, Rollup, Deno, Node, and Bun. Browser fixtures cover
dev and static serving where the bundler supports both, Chromium and Firefox,
direct runtime execution, the browser worker bridge, and solver thread settings
where the solver supports them.
For focused iteration, use npm run test:fixtures:browser,
npm run test:fixtures:runtime, or an individual fixture script such as
npm run test:fixture:node. The full matrix is the comprehensive check before
landing solver API, worker bridge, threading, or packaging changes.
See docs/api.md for the full TypeScript API reference covering CP-SAT, routing, MPSolver, MathOpt, PDLP, RCPSP, worker behavior, generated protobuf types, and native object cleanup.
Browser builds use WebAssembly threads, SIMD, and SharedArrayBuffer. Pages
must be served with cross-origin isolation enabled:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corpWithout these headers, browsers may block SharedArrayBuffer, and solving can
fail during WebAssembly runtime or worker startup.
Browser solves can run through a hidden worker bridge, so the main thread stays available for rendering, input, progress UI, and cancellation. The shared worker bridge controls apply across CP-SAT, routing, MPSolver, Knapsack, Network Flow, Set Cover, RCPSP, MathOpt, and PDLP:
import { isWorkerBridgeEnabled, setWorkerBridgeEnabled } from 'or-tools-wasm/cp-sat';
setWorkerBridgeEnabled(true);
console.log(isWorkerBridgeEnabled());Worker bridge support is separate from solver threading. For example, GLPK and BOP are single-threaded in this package but can still run through the browser worker bridge, while CP-SAT, SAT, SCIP/GSCIP, CBC, RCPSP, and other threaded-capable paths may also accept solver thread settings. Knapsack and Network Flow can run through the worker bridge but do not expose solver thread settings. Set Cover is also single-threaded and worker-bridge capable. The package loads solver runtimes on demand; application code does not need to choose between JSPI and Asyncify manually.
For Vite dev and preview servers, set the headers in vite.config.ts:
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
preview: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
});See docs/bundlers.md for Vite, Webpack, and Rollup setup.
Node and Bun work with normal ESM imports and do not need browser cross-origin-isolation headers.
Deno needs permissions to read package assets and inspect CPU count:
deno run --allow-read --allow-sys=cpus your-script.tsDeno and Bun use the Asyncify runtime path. Node uses JSPI when available and falls back to Asyncify otherwise.
npm install
npm run dev
npm run build
npm run previewnpm run dev / npm run start builds the library and launches the demo site.
npm run build runs the full WebAssembly, package, and static site build.
The Emscripten SDK is tracked as a pinned emsdk git submodule. The build
script initializes that submodule automatically if needed, so a normal clone can
run npm run build directly after npm install. If you prefer to fetch
submodules up front, clone with --recurse-submodules or run
git submodule update --init --recursive.
This repository vendors Google OR-Tools and adds a JavaScript/WebAssembly packaging layer on top. OR-Tools is Google's open-source suite for solving combinatorial optimization problems, including CP-SAT, linear programming, routing, bin packing, and graph algorithms.
Upstream project:
- Source: github.com/google/or-tools
- Documentation: developers.google.com/optimization
- License: Apache License 2.0
Maintained by Axel Wickman.
This project is licensed under the Apache License 2.0. See LICENSE.




