Home Manual Reference Source Test

src/controller/solving.js

  1. /** @external {minizinc} https://www.npmjs.com/package/minizinc */
  2. import { Model, init, solvers } from "../../assets/vendor/minizinc.mjs";
  3. /**
  4. * Initialize the MiniZinc WASM engine; must run before any solveModel() call.
  5. * @return {Promise<Array<Object>>} List of available solvers (each with id etc.).
  6. */
  7. export async function initSolvers() {
  8. await init();
  9. return solvers();
  10. }
  11. /**
  12. * Wrap MiniZinc's event-based solver as a Promise.
  13. * Implements the solve() call from Thesis' Algorithm.
  14. * @param {string} modelName - Virtual filename for the MZN engine.
  15. * @param {string} modelString - MZN source: variables + hard constraints (H) + optional objective (S).
  16. * @param {string} solverId - Backend id (e.g. "gecode").
  17. * @return {Promise<{solution: ?Object, statistics: ?Object, status: string}>}
  18. * @throws {Error} If the solver fails to initialize, or wraps any solver-side failure via cause-chain.
  19. */
  20. export async function solveModel(modelName, modelString, solverId) {
  21. const model = new Model();
  22. model.addFile(modelName, modelString);
  23. const solve = model.solve({
  24. options: { solver: solverId, statistics: true },
  25. });
  26. if (!solve) {
  27. throw new Error(`Solver '${solverId}' failed to initialize.`);
  28. }
  29. let result;
  30. try {
  31. result = await solve;
  32. } catch (e) {
  33. console.error("Solver error:", e, JSON.stringify(e));
  34. const detail =
  35. [e?.message, e?.stderr, e?.output].find(Boolean) ?? JSON.stringify(e);
  36. throw new Error(
  37. `Solver failed (code ${e?.code}, type ${e?.type}): ${detail}`,
  38. { cause: e },
  39. );
  40. }
  41. if (!["SATISFIED", "OPTIMAL_SOLUTION"].includes(result.status)) {
  42. console.info(`Solver status: ${result.status}`, result);
  43. }
  44. const { solution, statistics, status } = result;
  45. return { solution, statistics, status };
  46. }