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.
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>
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.
This requires an existing installation of MiniZinc.
Add the library with:
npm install minizinc
Then import it with:
// If using ESM
import * as MiniZinc from 'minizinc';
// If using CommonJS
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.
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({
// If omitted, searches for minizinc-worker.js next to the minizinc library script
workerURL: 'http://localhost:3000/path/to/my-own-worker.js',
// If these are omitted, searches next to the worker script
wasmURL: 'http://localhost:3000/path/to/minizinc.wasm',
dataURL: 'http://localhost:3000/path/to/minizinc.data'
}).then(() => {
console.log('Ready');
});
In NodeJS:
MiniZinc.init({
// Executable name
minizinc: 'minizinc',
// Search paths (can omit to use PATH)
minizincPaths: ['/home/me/.local/bin', '/usr/local/bin']
});
By default, the NodeJS version tries to find MiniZinc on your PATH
.
The main entrypoint for using the library is through the
Model
class:
const model = new MiniZinc.Model();
// Add a file with a given name and string contents
model.addFile('test.mzn', 'var 1..3: x; int: y;');
// If you're using NodeJS, you can add files from the filesystem directly
model.addFile('test.mzn');
// Add model code from a string
model.addString('int: z;');
// Add data in DZN format
model.addDznString('y = 1;');
// Add data from a JSON object
model.addJSON({z: 2});
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
}
});
// You can listen for events
solve.on('solution', solution => console.log(solution.output.json));
solve.on('statistics', stats => console.log(stats.statistics));
// And/or wait until complete
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.
For more detailed documentation of all available options and functionality, visit the API documentation.
The WebAssembly build of MiniZinc requires Emscripten.
# Clone MiniZinc
git clone https://github.com/MiniZinc/libminizinc minizinc
# Download solvers (or you can build them yourself using emscripten)
cd minizinc
MZNARCH=wasm ./download_vendor
# Configure MiniZinc
emcmake cmake -S . -B build \
-DCMAKE_FIND_ROOT_PATH="/" \
-DCMAKE_BUILD_TYPE=Release \
-DGecode_ROOT="$PWD/vendor/gecode" \
-DOsiCBC_ROOT="$PWD/vendor/cbc" \
-DCMAKE_PREFIX_PATH="$PWD/vendor/highs/lib/cmake/highs:$PWD/vendor/chuffed/lib/cmake/chuffed" \
-DCMAKE_INSTALL_PREFIX="../minizinc-install"
# Build MiniZinc
cmake --build build --config Release --target install
The WebAssembly build of MiniZinc can also be obtained from the build workflow as the minizinc
artifact.
- Run
npm install
to install dependencies. - Place the
bin/
folder of the WebAssembly build of MiniZinc inside this directory. Alternatively set theMZN_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 thedist/
directory. - Run
npm run docs
to build the documentation. The output files are in thedocs/
directory.
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.
This library is distributed under the Mozilla Public License Version 2.0. See LICENSE for more information.