All files / src/controller solving.js

100% Statements 16/16
100% Branches 6/6
100% Functions 2/2
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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