GithubHelp home page GithubHelp logo

minizinc / minizinc-js Goto Github PK

View Code? Open in Web Editor NEW
20.0 11.0 6.0 804 KB

Use MiniZinc in the browser or with NodeJS

Home Page: https://js.minizinc.dev

License: Mozilla Public License 2.0

JavaScript 100.00%
constraint-programming integer-programming javascript linear-programming minizinc optimisation-problem sat-solver typescript-definitions nodejs webassembly

minizinc-js's Introduction

JavaScript interface for MiniZinc

Latest documentation Latest package Edge documentation Edge package

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:

// 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.

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({
  // 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.

Creating Models

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

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.

Documentation

For more detailed documentation of all available options and functionality, visit the API documentation.

Building

Compiling MiniZinc for WebAssembly

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.

Building MiniZinc JS

  1. Run npm install to install dependencies.
  2. 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.
  3. Run npm run build to build the package. The built files are in the dist/ directory.
  4. 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.

minizinc-js's People

Contributors

cyderize avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

minizinc-js's Issues

message: 'Error: no model file given.', type: 'exit', code: 1

Hi,
I found this issue when I using 4.3.1 version of this lib. And I tried to add some log in the compressed code 'minizinc-node.mjs'.
I found the file name isn't added to _toRun list correctly.
image

I also tried to copy 'node.js' file to my local environment and replaced packaged lib. With the same code. It works good. Seems like there might be wrong somewhere. Perhaps needto release a new version?

Options `timeout` and `num-solutions` make solver return error

Minimal example from the README.

const model = new MiniZinc.Model();
  model.addFile('test.mzn', 'var 1..3: x;');
  const solve = model.solve({
    options: {
      timeout: 10000,   # this will fail
      'num-solutions': 100,  # this will fail
      solver: 'gecode',
      'all-solutions': true
    }
  });
  solve.on('solution', solution => {
    console.log(solution.output.json);
  });
  solve.then(result => {
    console.log(result.status);
  });

This code fails with the following error.

minizinc.js:1 Uncaught {type: 'exit', code: 1}
n @ minizinc.js:1
s.onmessage @ minizinc.js:1

Note, the error message is absent, so it's hard to troubleshoot what exactly is failing.

OR-tools support

Hi!

Is it currently possible to manually include Google OR-tools in the compilation of minizinc-js?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.