JavaScript interface for MiniZinc

This package provides a JavaScript API for MiniZinc
for use in web browsers using WebAssembly, or in NodeJS using a native
installation of MiniZinc.
This library powers the MiniZinc Playground.
Getting started
Using a CDN (recommended)
Using ECMAScript modules:
<script type="module">
import { Model } from 'https://cdn.jsdelivr.net/npm/minizinc/dist/minizinc.mjs';
const model = new Model();
model.addFile('test.mzn', 'var 1..3: x;');
const solve = model.solve({
options: {
solver: 'gecode',
'all-solutions': true,
},
});
solve.on('solution', solution => {
console.log(solution.output.json);
});
solve.then(result => {
console.log(result.status);
});
</script>
Using a traditional script:
<script src="https://cdn.jsdelivr.net/npm/minizinc/dist/minizinc.js"></script>
<script>
const model = new MiniZinc.Model();
model.addFile('test.mzn', 'var 1..3: x;');
const solve = model.solve({
options: {
solver: 'gecode',
'all-solutions': true,
},
});
solve.on('solution', solution => {
console.log(solution.output.json);
});
solve.then(result => {
console.log(result.status);
});
</script>
Self-hosting WebAssembly files
If you’re using a bundler, you can add the library to your project:
npm install minizinc
Then import it with:
import * as MiniZinc from 'minizinc';
These three files need to be served by your webserver (found in node_modules/minizinc/dist):
minizinc-worker.js
minizinc.wasm
minizinc.data
If you place them alongside your bundled script, they should be found automatically.
Otherwise, their URLs can be specified during initialisation.
In NodeJS
This requires an existing installation of MiniZinc.
Add the library with:
npm install minizinc
Then import it with:
import * as MiniZinc from 'minizinc';
const MiniZinc = require('minizinc');
If you have added MiniZinc to your PATH, it will be found automatically.
Otherwise, you can specify the executable path during initialisation.
Usage
Initialisation
Initialisation happens automatically when the library is used, or by calling
init(...). This can be used to ensure
that the WebAssembly files start loading immediately, or to specify a different URL for the worker
(or path to the MiniZinc executable if using NodeJS).
In the browser:
MiniZinc.init({
workerURL: 'http://localhost:3000/path/to/my-own-worker.js',
wasmURL: 'http://localhost:3000/path/to/minizinc.wasm',
dataURL: 'http://localhost:3000/path/to/minizinc.data',
}).then(() => {
console.log('Ready');
});
In NodeJS:
MiniZinc.init({
minizinc: 'minizinc',
minizincPaths: ['/home/me/.local/bin', '/usr/local/bin'],
});
By default, the NodeJS version tries to find MiniZinc on your PATH.
Creating Models
The main entrypoint for using the library is through the
Model class:
const model = new MiniZinc.Model();
model.addFile('test.mzn', 'var 1..3: x; int: y;');
model.addFile('test.mzn');
model.addString('int: z;');
model.addDznString('y = 1;');
model.addJson({ z: 2 });
Solving
Solving is done using the Model.solve(...) method,
which takes an object with options in .mpc
format.
const solve = model.solve({
options: {
solver: 'gecode',
'time-limit': 10000,
statistics: true,
},
});
solve.on('solution', solution => console.log(solution.output.json));
solve.on('statistics', stats => console.log(stats.statistics));
solve.then(result => {
console.log(result.solution.output.json);
console.log(result.statistics);
});
During solving, MiniZinc emits events which can be subscribed to/unsubscribed from using the
SolveProgress.on /
SolveProgress.off
methods. The events are those which appear in
Machine-readable JSON output format,
with the addition of the exit
event, which can be used to detect when solving finishes (if you do not wish to await the
SolveProgress object).
By default, --output-mode json is used, allowing you to retrieve the model variable values
directly from the solution objects. Use
Model.solve({ jsonOutput: false, ...})
(and optionally specify a different output-mode in the options) to disable this behaviour.
Documentation
For more detailed documentation of all available options and functionality, visit the
API documentation.
Building
Compiling MiniZinc for WebAssembly
CI downloads minizinc-compiler-only-wasm32-emscripten.tar.gz from libminizinc’s
releases (edge for the
development version) rather than building it, which is also the easiest way to get
one locally.
To build it yourself you need Emscripten, at the version
pinned as emsdk in libminizinc’s vendor.lock: the solver archives are built with
it, and mixing emscripten versions across static archives is not safe.
# Clone MiniZinc
git clone https://github.com/MiniZinc/libminizinc minizinc
cd minizinc
# Download the solvers built for wasm (requires the gh CLI, authenticated)
scripts/fetch_vendor.sh wasm32-emscripten gecode cbc chuffed highs
# Configure and build, exactly as CI does
ROOT="$PWD" CMAKE_WRAPPER=emcmake CMAKE_FIND_ROOT_PATH=/ \
CMAKE_GENERATOR="Unix Makefiles" EXPECT_DEPS="gecode cbc chuffed highs" \
bash scripts/build.sh
This installs into minizinc/ (bin/minizinc.js, .wasm and .data).
Building MiniZinc JS
- Run
npm install to install dependencies.
- Place the
bin/ folder of the WebAssembly build of MiniZinc inside this directory.
Alternatively set the MZN_WASM_DIR environment variable to the installation directory of the
WebAssembly build of MiniZinc.
- Run
npm run build to build the package. The built files are in the dist/ directory.
- Run
npm run docs to build the documentation. The output files are in the docs/ directory.
Testing
When testing, the web-worker library is used to emulate Web Worker
support in NodeJS. This allows us to test both the browser version using WebAssembly, as well as the native version.
Run npm test to run tests using Jest.
License
This library is distributed under the Mozilla Public License Version 2.0. See LICENSE for more information.
评论