### Install glpk.js Source: https://github.com/jvail/glpk.js/blob/master/README.md Install the glpk.js package using npm. ```sh npm install glpk.js ``` -------------------------------- ### Minimal LP Example Source: https://github.com/jvail/glpk.js/blob/master/README.md Sets up and solves a simple linear programming problem using the glpk.js library. Requires importing GLPK and awaiting its initialization. ```js import GLPK from 'glpk.js'; const glpk = await GLPK(); const options = { msglev: glpk.GLP_MSG_ALL, presol: true }; const result = await glpk.solve({ name: 'LP', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [ { name: 'x1', coef: 0.6 }, { name: 'x2', coef: 0.5 } ] }, subjectTo: [ { name: 'cons1', vars: [ { name: 'x1', coef: 1.0 }, { name: 'x2', coef: 2.0 } ], bnds: { type: glpk.GLP_UP, ub: 1.0, lb: 0.0 } }, { name: 'cons2', vars: [ { name: 'x1', coef: 3.0 }, { name: 'x2', coef: 1.0 } ], bnds: { type: glpk.GLP_UP, ub: 2.0, lb: 0.0 } } ] }, options); ``` -------------------------------- ### TypeScript Import Example Source: https://github.com/jvail/glpk.js/blob/master/README.md Example of how to import GLPK and its types in a TypeScript Node.js environment. ```APIDOC ## TypeScript Node.js Import ### Description Demonstrates how to import the GLPK solver and associated types in a TypeScript project for Node.js. ### Method Use `import` statements with the `glpk.js/node` path. ### Code Example ```typescript /* typescript node import */ import GLPK, { type LP, type Options, type Result } from 'glpk.js/node'; // Initialize GLPK const glpk = await GLPK(); // Example usage with types: // const lpProblem: LP = { ... }; // const solverOptions: Options = { ... }; // const solution: Result = await glpk.solve(lpProblem, solverOptions); ``` ``` -------------------------------- ### Build with emsdk Source: https://github.com/jvail/glpk.js/blob/master/README.md Build the glpk.js project using emsdk. This involves cloning the repository, initializing submodules, installing dependencies, setting up the emsdk environment, and running build and test commands. ```sh git clone https://github.com/jvail/glpk.js.git cd glpk.js git submodule update --init --recursive npm install source ~/emsdk/emsdk_env.sh npm run build && npm run test ``` -------------------------------- ### TypeScript Usage Example Source: https://context7.com/jvail/glpk.js/llms.txt Leverage full TypeScript definitions for all types by importing them from the 'glpk.js/node' entry point. Ensure proper handling of optional properties like `dual` and `rows` when they are expected. ```typescript import GLPK, { type LP, type Options, type Result } from 'glpk.js/node'; const glpk = await GLPK(); const problem: LP = { name: 'ts_example', objective: { direction: glpk.GLP_MAX, name: 'revenue', vars: [ { name: 'product_a', coef: 25 }, { name: 'product_b', coef: 30 } ] }, subjectTo: [ { name: 'machine_hours', vars: [{ name: 'product_a', coef: 20 }, { name: 'product_b', coef: 12 }], bnds: { type: glpk.GLP_UP, ub: 1800, lb: 0 } }, { name: 'labor_hours', vars: [{ name: 'product_a', coef: 1 / 15 }, { name: 'product_b', coef: 1 / 15 }], bnds: { type: glpk.GLP_UP, ub: 8, lb: 0 } } ] }; const options: Options = { msglev: glpk.GLP_MSG_ERR, presol: true, rows: true }; const result: Result = glpk.solve(problem, options); if (result.result.status === glpk.GLP_OPT) { const { z, vars, dual, rows } = result.result; console.log(`Optimal revenue: $${z}`); console.log('product_a units:', vars['product_a']); console.log('product_b units:', vars['product_b']); console.log('Shadow price — machine_hours:', dual!['machine_hours']); } ``` -------------------------------- ### Initialize GLPK.js in Browser (Async/Web Worker) Source: https://context7.com/jvail/glpk.js/llms.txt Initialize the GLPK solver in the browser. This spawns a Web Worker and loads the WASM binary. Constants are available on the instance. ```javascript import GLPK from 'glpk.js'; // Initialize the solver (spawns Web Worker + loads WASM) const glpk = await GLPK(); console.log('GLPK version:', glpk.version); // e.g. "5.0" // Constants are available on the instance: // glpk.GLP_MAX, glpk.GLP_MIN // glpk.GLP_FR, glpk.GLP_LO, glpk.GLP_UP, glpk.GLP_DB, glpk.GLP_FX // glpk.GLP_MSG_OFF, GLP_MSG_ERR, GLP_MSG_ON, GLP_MSG_ALL, GLP_MSG_DBG // glpk.GLP_UNDEF, GLP_FEAS, GLP_INFEAS, GLP_NOFEAS, GLP_OPT, GLP_UNBND ``` -------------------------------- ### Build with Docker Source: https://github.com/jvail/glpk.js/blob/master/README.md Build the glpk.js project using Docker. This command builds the Docker image and then runs a container to execute the build process, mounting the current directory to the container. ```sh docker build . -t glpk.js docker run -v $PWD:/app glpk.js ``` -------------------------------- ### GLPK Solver Initialization and Usage Source: https://github.com/jvail/glpk.js/blob/master/README.md This snippet demonstrates how to initialize the GLPK solver and use its `solve` method to define and solve an LP problem. It includes setting up the objective function, constraints, and solver options. ```APIDOC ## Initialize and Solve LP ### Description Initializes the GLPK solver and solves a linear programming problem. ### Method `await GLPK()` to initialize, then `await glpk.solve(lp, options)` to solve. ### Parameters #### `lp` Object - **name** (string) - The name of the LP problem. - **objective** (object) - Defines the objective function. - **direction** (number) - `glpk.GLP_MAX` or `glpk.GLP_MIN`. - **name** (string) - The name of the objective function. - **vars** (array of objects) - Variables in the objective function. - **name** (string) - Variable name. - **coef** (number) - Coefficient of the variable. - **subjectTo** (array of objects) - Constraints for the LP. - **name** (string) - Constraint name. - **vars** (array of objects) - Variables in the constraint. - **name** (string) - Variable name. - **coef** (number) - Coefficient of the variable. - **bnds** (object) - Bounds for the constraint. - **type** (number) - Constraint type (e.g., `glpk.GLP_UP`, `glpk.GLP_LO`, `glpk.GLP_FX`). - **ub** (number) - Upper bound (if applicable). - **lb** (number) - Lower bound (if applicable). - **bounds** (array of objects, optional) - Additional bounds for variables. - **name** (string) - Bound name. - **type** (number) - Bound type. - **ub** (number) - Upper bound. - **lb** (number) - Lower bound. - **binaries** (array of strings, optional) - Names of binary variables. - **generals** (array of strings, optional) - Names of general (integer) variables. #### `options` Object (optional) - **msglev** (number) - Message level for solver output (e.g., `glpk.GLP_MSG_ALL`). - **presol** (boolean) - Whether to use the presolver. ### Request Example ```javascript const glpk = await GLPK(); const options = { msglev: glpk.GLP_MSG_ALL, presol: true }; const result = await glpk.solve({ name: 'LP', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [ { name: 'x1', coef: 0.6 }, { name: 'x2', coef: 0.5 } ] }, subjectTo: [ { name: 'cons1', vars: [ { name: 'x1', coef: 1.0 }, { name: 'x2', coef: 2.0 } ], bnds: { type: glpk.GLP_UP, ub: 1.0, lb: 0.0 } }, { name: 'cons2', vars: [ { name: 'x1', coef: 3.0 }, { name: 'x2', coef: 1.0 } ], bnds: { type: glpk.GLP_UP, ub: 2.0, lb: 0.0 } } ] }, options); ``` ### Response #### Success Response (result object) - **result** (object) - Contains the solution details. - **vars** (array of objects) - Solution values for variables. - **name** (string) - Variable name. - **value** (number) - Optimal value of the variable. - **z** (number) - Optimal objective function value. #### Response Example ```json { "vars": [ { "name": "x1", "value": 0.2 }, { "name": "x2", "value": 0.4 } ], "z": 0.32 } ``` ``` -------------------------------- ### Initialize GLPK.js in Node.js (Sync Solver) Source: https://context7.com/jvail/glpk.js/llms.txt Initialize the GLPK solver for Node.js. The factory is still async, but solve() returns values synchronously. Requires Node.js ≥ 20. ```javascript import GLPK from 'glpk.js/node'; // TypeScript import with types: // import GLPK, { type LP, type Options, type Result } from 'glpk.js/node'; const glpk = await GLPK(); // solve() returns Result directly (not a Promise) in Node.js const result = glpk.solve({ name: 'simple', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [{ name: 'x', coef: 1 }] }, subjectTo: [ { name: 'c1', vars: [{ name: 'x', coef: 1 }], bnds: { type: glpk.GLP_UP, ub: 10, lb: 0 } } ] }); console.log(result); // { // name: 'simple', // time: 0.001, // result: { status: 5, z: 10, vars: { x: 10 }, dual: { c1: 1 } } // } ``` -------------------------------- ### GLPK() Factory Function (Browser) Source: https://context7.com/jvail/glpk.js/llms.txt Initializes the GLPK solver in the browser, spawning a Web Worker and loading the WASM binary. Returns a Promise that resolves to a GLPK instance. ```APIDOC ## GLPK() (Browser, async/Web Worker) The default export from `glpk.js` is a factory that returns a `Promise`. In the browser it spawns a Web Worker backed by the embedded WASM binary. The returned instance exposes all `GLP_*` constants and the `solve`, `write`, and `terminate` methods. ```js import GLPK from 'glpk.js'; // Initialize the solver (spawns Web Worker + loads WASM) const glpk = await GLPK(); console.log('GLPK version:', glpk.version); // e.g. "5.0" // Constants are available on the instance: // glpk.GLP_MAX, glpk.GLP_MIN // glpk.GLP_FR, glpk.GLP_LO, glpk.GLP_UP, glpk.GLP_DB, glpk.GLP_FX // glpk.GLP_MSG_OFF, GLP_MSG_ERR, GLP_MSG_ON, GLP_MSG_ALL, GLP_MSG_DBG // glpk.GLP_UNDEF, glpk.GLP_FEAS, glpk.GLP_INFEAS, glpk.GLP_NOFEAS, glpk.GLP_OPT, glpk.GLP_UNBND ``` ``` -------------------------------- ### Configure Solver Options for LP/MIP with glpk.js Source: https://context7.com/jvail/glpk.js/llms.txt Customize solver behavior using the `Options` object, including message levels, presolver settings, time limits, MIP gap tolerance, and enabling constraint values in the result. An iteration callback can be provided for LPs. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); const lp = { name: 'configured', objective: { direction: glpk.GLP_MIN, name: 'cost', vars: [{ name: 'x', coef: 2 }, { name: 'y', coef: 3 }] }, subjectTo: [ { name: 'budget', vars: [{ name: 'x', coef: 1 }, { name: 'y', coef: 1 }], bnds: { type: glpk.GLP_LO, lb: 4, ub: 0 } // x + y >= 4 } ] }; /** @type {import('glpk.js/node').Options} */ const options = { msglev: glpk.GLP_MSG_ERR, // only errors/warnings (default) presol: true, // enable presolver (default true) tmlim: 30, // time limit in seconds mipgap: 0.05, // 5% relative MIP gap tolerance rows: true, // include row/constraint values in Result // cb: iteration callback (LP only, disables presolver) cb: { call: (partialResult) => { // called every `each` simplex iterations console.log('Iteration z =', partialResult.z); }, each: 10 } }; const result = glpk.solve(lp, options); console.log('Status:', result.result.status === glpk.GLP_OPT ? 'OPTIMAL' : 'OTHER'); console.log('z:', result.result.z); console.log('rows:', result.result.rows); // { budget: 4 } console.log('time (s):', result.time); ``` -------------------------------- ### Initialize and Run Memory Test Source: https://github.com/jvail/glpk.js/blob/master/test/mem.html Initializes GLPK, generates a problem, and runs a memory test for a specified number of iterations. Terminates the worker after completion. ```javascript import GLPK from '../dist/index.js'; import { runMemoryTest, runParallelWorkerTest, generateLargeProblem, getMemoryUsage } from './mem-test.js'; const output = document.getElementById('output'); const runBtn = document.getElementById('runBtn'); const parallelOptions = document.getElementById('parallelOptions'); function log(msg, className = '') { const line = document.createElement('div'); line.textContent = msg; if (className) line.className = className; output.appendChild(line); output.scrollTop = output.scrollHeight; } function getSelectedMode() { return document.querySelector('input[name="mode"]:checked').value; } window.updateMode = function() { const mode = getSelectedMode(); if (mode === 'parallel') { parallelOptions.classList.add('visible'); } else { parallelOptions.classList.remove('visible'); } }; window.clearOutput = function() { output.innerHTML = ''; }; window.runTest = async function() { runBtn.disabled = true; output.innerHTML = ''; const mode = getSelectedMode(); const iterations = parseInt(document.getElementById('iterations').value, 10); const numVars = parseInt(document.getElementById('numVars').value, 10); const numConstraints = parseInt(document.getElementById('numConstraints').value, 10); const mip = document.getElementById('mip').checked; try { const mem = getMemoryUsage(); if (!mem) { log('Note: Memory API not available. Use Chrome with --enable-precise-memory-info flag.', 'info'); } if (mode === 'parallel') { // Parallel workers test const numWorkers = parseInt(document.getElementById('numWorkers').value, 10); log(`=== Parallel Workers Test (Issue #47) ===`, 'info'); log(`Testing ${numWorkers} independent GLPK/WASM instances`, 'info'); log('', 'info'); const result = await runParallelWorkerTest(GLPK, { numWorkers, iterations, numVars, numConstraints, mip, log: (msg, className) => { // Color worker messages differently, or use provided class if if (className) { log(msg, className); } else { const isWorkerMsg = msg.startsWith('[Worker'); log(msg, isWorkerMsg ? 'worker' : ''); } } }); log('', 'info'); if (result.success) { log('All workers completed successfully!', 'success'); } else { const failedCount = result.workerResults.filter(r => !r.success).length; log(`${failedCount}/${result.numWorkers} workers failed.`, 'error'); } } else { // Single worker test (original behavior) log('Initializing GLPK (web worker)...', 'info'); const glpk = await GLPK(); log(`GLPK version: ${glpk.version}`, 'info'); const problemType = mip ? 'MIP' : 'LP'; log(`Generating ${problemType} problem...`, 'info'); const lp = generateLargeProblem(glpk, { numVars, numConstraints, mip }); if (mip) { log(`Binary vars: ${lp.binaries?.length ?? 0}, Integer vars: ${lp.generals?.length ?? 0}`, 'info'); } const result = await runMemoryTest(glpk, { iterations, lp, log: (msg) => log(msg) }); if (result.success) { log('Test completed successfully!', 'success'); } else { log('Test completed with failures.', 'error'); } // Terminate worker to clean up if (glpk.terminate) { glpk.terminate(); log('Worker terminated.', 'info'); } } } catch (err) { log(`Error: ${err.message}`, 'error'); console.error(err); } finally { runBtn.disabled = false; } }; ``` -------------------------------- ### GLPK() Factory Function (Node.js) Source: https://context7.com/jvail/glpk.js/llms.txt Initializes the GLPK solver for Node.js. The factory is still async, but `solve` and `write` return values synchronously once initialized. Requires Node.js ≥ 20. ```APIDOC ## GLPK() (Node.js, sync solver) Import from `glpk.js/node` for Node.js. The factory is still async (WASM initialization), but `solve` and `write` return values synchronously once initialized. Requires Node.js ≥ 20. ```js import GLPK from 'glpk.js/node'; // TypeScript import with types: // import GLPK, { type LP, type Options, type Result } from 'glpk.js/node'; const glpk = await GLPK(); // solve() returns Result directly (not a Promise) in Node.js const result = glpk.solve({ name: 'simple', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [{ name: 'x', coef: 1 }] }, subjectTo: [ { name: 'c1', vars: [{ name: 'x', coef: 1 }], bnds: { type: glpk.GLP_UP, ub: 10, lb: 0 } } ] }); console.log(result); // { // name: 'simple', // time: 0.001, // result: { status: 5, z: 10, vars: { x: 10 }, dual: { c1: 1 } } // } ``` ``` -------------------------------- ### Variable Bounds Demonstration in GLPK Source: https://context7.com/jvail/glpk.js/llms.txt Illustrates the use of different GLPK bound types for variables, including free, lower bounded, upper bounded, double bounded, and fixed variables. These bounds can be set directly on variables or within constraints. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); // Bound type reference: // GLP_FR (1): free variable, -Inf <= x <= +Inf // GLP_LO (2): lower bounded, lb <= x <= +Inf // GLP_UP (3): upper bounded, -Inf <= x <= ub // GLP_DB (4): double bounded, lb <= x <= ub // GLP_FX (5): fixed (equality), x = lb = ub const lp = { name: 'bounds_demo', objective: { direction: glpk.GLP_MIN, name: 'obj', vars: [ { name: 'free_var', coef: 1 }, { name: 'lower_var', coef: 1 }, { name: 'upper_var', coef: 1 }, { name: 'double_var', coef: 1 }, { name: 'fixed_var', coef: 1 } ] }, subjectTo: [ { name: 'sum_constraint', vars: [ { name: 'free_var', coef: 1 }, { name: 'lower_var', coef: 1 }, { name: 'upper_var', coef: 1 }, { name: 'double_var', coef: 1 }, { name: 'fixed_var', coef: 1 } ], bnds: { type: glpk.GLP_LO, lb: 5, ub: 0 } // sum >= 5 } ], bounds: [ { name: 'free_var', type: glpk.GLP_FR, lb: 0, ub: 0 }, // unbounded { name: 'lower_var', type: glpk.GLP_LO, lb: 2, ub: 0 }, // >= 2 { name: 'upper_var', type: glpk.GLP_UP, lb: 0, ub: 10 }, // <= 10 { name: 'double_var', type: glpk.GLP_DB, lb: 1, ub: 5 }, // 1..5 { name: 'fixed_var', type: glpk.GLP_FX, lb: 3, ub: 3 } // = 3 ] }; const result = glpk.solve(lp); console.log('Status:', result.result.status); // GLP_OPT (5) console.log('Variables:', result.result.vars); ``` -------------------------------- ### Minimize MILP with Binary Variables Source: https://context7.com/jvail/glpk.js/llms.txt Demonstrates how to define and solve a Mixed Integer Linear Programming problem where some variables are constrained to be binary (0 or 1). The solver automatically switches to branch-and-bound for such problems. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); // Minimize -x1 - 2*x2 + 0.1*x3 + 3*x4 // x3, x4 are binary (0 or 1) const mipBin = { name: 'mip_with_binaries', objective: { direction: glpk.GLP_MIN, name: 'obj', vars: [ { name: 'x1', coef: -1 }, { name: 'x2', coef: -2 }, { name: 'x3', coef: 0.1 }, { name: 'x4', coef: 3 } ] }, subjectTo: [ { name: 'c1', vars: [{ name: 'x1', coef: 1 }, { name: 'x2', coef: 1 }], bnds: { type: glpk.GLP_UP, ub: 5, lb: 0 } // x1 + x2 <= 5 }, { name: 'c2', vars: [{ name: 'x1', coef: 2 }, { name: 'x2', coef: -1 }], bnds: { type: glpk.GLP_LO, lb: 0, ub: 0 } // 2*x1 - x2 >= 0 }, { name: 'c3', vars: [{ name: 'x1', coef: -1 }, { name: 'x2', coef: 3 }], bnds: { type: glpk.GLP_LO, lb: 0, ub: 0 } // -x1 + 3*x2 >= 0 }, { name: 'c4', vars: [{ name: 'x3', coef: 1 }, { name: 'x4', coef: 1 }], bnds: { type: glpk.GLP_LO, lb: 0.5, ub: 0 } // x3 + x4 >= 0.5 } ], binaries: ['x3', 'x4'] // x3, x4 ∈ {0, 1} }; const result = glpk.solve(mipBin, { msglev: glpk.GLP_MSG_OFF }); console.log('Optimal z:', result.result.z); // -8.233... console.log('Vars:', result.result.vars); // { x1: 1.666..., x2: 1.666..., x3: 1, x4: 0 } ``` -------------------------------- ### Time-Limited Solving with GLPK Source: https://context7.com/jvail/glpk.js/llms.txt Demonstrates how to limit the solver's execution time using the `tmlim` option. If the time limit is reached, the solution status will be `GLP_UNDEF`, and variables will reflect the last known state. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); const lp = JSON.parse(/* large MILP JSON */`{ "name": "hard_mip", "objective": { "direction": 1, "name": "obj", "vars": [{ "name": "x1", "coef": -1 }] }, "subjectTo": [ { "name": "c1", "vars": [{ "name": "x1", "coef": 1 }], "bnds": { "type": 3, "ub": 100, "lb": 0 } } ], "generals": ["x1"] }`); const result = glpk.solve(lp, { tmlim: 0.001 }); // 1ms — almost certainly not enough if (result.result.status === glpk.GLP_UNDEF) { console.log('Time limit hit — solution undefined'); console.log('Last z:', result.result.z); // 0 console.log('Last x1:', result.result.vars.x1); // 0 } else { console.log('Solved in time:', result.time, 's'); } ``` -------------------------------- ### glpk.solve(lp, options?) Source: https://context7.com/jvail/glpk.js/llms.txt Solves a linear or mixed-integer program defined by an `LP` object. Returns a `Promise` in the browser and a `Result` directly in Node.js. Automatically selects the simplex method (LP) or branch-and-bound (MILP) based on whether `generals` or `binaries` are present. ```APIDOC ## glpk.solve(lp, options?) — Solve LP or MILP Solves a linear or mixed-integer program defined by an `LP` object. Returns a `Promise` in the browser and a `Result` directly in Node.js. Automatically selects the simplex method (LP) or branch-and-bound (MILP) based on whether `generals` or `binaries` are present. ```js import GLPK from 'glpk.js/node'; const glpk = await GLPK(); // --- LP: Maximize 0.6*x1 + 0.5*x2 --- // subject to: // x1 + 2*x2 <= 1 // 3*x1 + x2 <= 2 // x1, x2 >= 0 (default lower bound) const lp = { name: 'LP', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [ { name: 'x1', coef: 0.6 }, { name: 'x2', coef: 0.5 } ] }, subjectTo: [ { name: 'cons1', vars: [ { name: 'x1', coef: 1.0 }, { name: 'x2', coef: 2.0 } ], bnds: { type: glpk.GLP_UP, ub: 1.0, lb: 0.0 } }, { name: 'cons2', vars: [ { name: 'x1', coef: 3.0 }, { name: 'x2', coef: 1.0 } ], bnds: { type: glpk.GLP_UP, ub: 2.0, lb: 0.0 } } ] }; const result = glpk.solve(lp, { msglev: glpk.GLP_MSG_ALL, // full solver output presol: true, // use presolver rows: true // include constraint values in result }); if (result.result.status === glpk.GLP_OPT) { console.log('Optimal objective:', result.result.z); // 0.46 console.log('Variables:', result.result.vars); // { x1: 0.6, x2: 0.2 } console.log('Dual values:', result.result.dual); // { cons1: 0.1, cons2: 0.2 } console.log('Row values:', result.result.rows); // { cons1: 1.0, cons2: 2.0 } } else { console.error('No optimal solution, status:', result.result.status); } ``` ``` -------------------------------- ### Options Interface - Solver Configuration Source: https://context7.com/jvail/glpk.js/llms.txt Controls the behavior of the GLPK solver, including message levels, presolver settings, time limits, MIP gap tolerance, and iteration callbacks for LPs. ```APIDOC ## `Options` Interface — Solver Configuration The `Options` object controls solver behavior: verbosity, time limits, MIP gap tolerance, whether to include constraint values, and an iteration callback for LPs. ```js import GLPK from 'glpk.js/node'; const glpk = await GLPK(); const lp = { name: 'configured', objective: { direction: glpk.GLP_MIN, name: 'cost', vars: [{ name: 'x', coef: 2 }, { name: 'y', coef: 3 }] }, subjectTo: [ { name: 'budget', vars: [{ name: 'x', coef: 1 }, { name: 'y', coef: 1 }], bnds: { type: glpk.GLP_LO, lb: 4, ub: 0 } // x + y >= 4 } ] }; /** @type {import('glpk.js/node').Options} */ const options = { msglev: glpk.GLP_MSG_ERR, // only errors/warnings (default) presol: true, // enable presolver (default true) tmlim: 30, // time limit in seconds mipgap: 0.05, // 5% relative MIP gap tolerance rows: true, // include row/constraint values in Result // cb: iteration callback (LP only, disables presolver) cb: { call: (partialResult) => { // called every `each` simplex iterations console.log('Iteration z =', partialResult.z); }, each: 10 } }; const result = glpk.solve(lp, options); console.log('Status:', result.result.status === glpk.GLP_OPT ? 'OPTIMAL' : 'OTHER'); console.log('z:', result.result.z); console.log('rows:', result.result.rows); // { budget: 4 } console.log('time (s):', result.time); ``` ``` -------------------------------- ### Node.js TypeScript Import Source: https://github.com/jvail/glpk.js/blob/master/README.md Import GLPK and its types for use in a TypeScript Node.js environment. Initializes GLPK for synchronous use. ```ts /* typescript node import */ import GLPK, { type LP, type Options, type Result } from 'glpk.js/node'; glpk = await GLPK() ``` -------------------------------- ### Simplex Iteration Callback (Browser, Async) Source: https://context7.com/jvail/glpk.js/llms.txt Use the `cb` option to receive partial `Result` objects during simplex iterations for real-time progress display in the browser. This callback is not invoked for MIP problems. ```html ``` -------------------------------- ### Solve LP Problem and Interpret Results Source: https://context7.com/jvail/glpk.js/llms.txt Solves a linear programming problem and demonstrates how to interpret the returned result object, including checking the solution status. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); const result = glpk.solve({ name: 'example', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [{ name: 'x1', coef: 0.6 }, { name: 'x2', coef: 0.5 }] }, subjectTo: [ { name: 'cons1', vars: [{ name: 'x1', coef: 1 }, { name: 'x2', coef: 2 }], bnds: { type: glpk.GLP_UP, ub: 1, lb: 0 } } ] }, { rows: true }); // Result shape: // { // name: 'example', — problem name // time: 0.001, — solve time in seconds // result: { // status: 5, — GLP_OPT (optimal) // z: 0.3, — objective value // vars: { x1: 0, x2: 0.5 }, — primal variable values // dual: { cons1: 0.25 }, — dual/shadow prices (LP only) // rows: { cons1: 1.0 } — constraint LHS values (if rows: true) // } // } const { status, z, vars, dual, rows } = result.result; // Check solution status switch (status) { case glpk.GLP_OPT: console.log('Optimal, z =', z); break; case glpk.GLP_FEAS: console.log('Feasible (not optimal), z =', z); break; case glpk.GLP_INFEAS: console.log('Infeasible'); break; case glpk.GLP_NOFEAS: console.log('No feasible solution'); break; case glpk.GLP_UNBND: console.log('Unbounded'); break; case glpk.GLP_UNDEF: console.log('Undefined (e.g. time limit hit)'); break; } ``` -------------------------------- ### Define Binary Variables Source: https://github.com/jvail/glpk.js/blob/master/README.md Specify variables as binary by assigning their names to the 'binaries' array in the LP object. ```js /* binary */ lp.binaries = ['x3', 'x4']; ``` -------------------------------- ### write Source: https://context7.com/jvail/glpk.js/llms.txt Serializes an LP object into the CPLEX LP text format. This is useful for debugging or for interoperating with other LP solvers. The return type depends on the environment: a string in Node.js and a Promise in the browser. ```APIDOC ## `glpk.write(lp)` ### Description Exports an LP object to the CPLEX LP text format. This function is useful for debugging or for sharing problem definitions with other solvers. ### Parameters #### `lp` (object) - Required Represents the linear programming problem structure, same as used in the `solve` method. ### Response - **string** (Node.js) or **Promise** (Browser) - The problem definition in CPLEX LP format. ### Request Example ```javascript const lp = { name: 'MyProblem', objective: { direction: glpk.GLP_MAX, name: 'profit', vars: [ { name: 'chairs', coef: 45 }, { name: 'tables', coef: 80 } ] }, subjectTo: [ { name: 'wood', vars: [{ name: 'chairs', coef: 5 }, { name: 'tables', coef: 20 }], bnds: { type: glpk.GLP_UP, ub: 400, lb: 0 } }, { name: 'labor', vars: [{ name: 'chairs', coef: 10 }, { name: 'tables', coef: 15 }], bnds: { type: glpk.GLP_UP, ub: 450, lb: 0 } } ] }; // Node.js: const cplex = glpk.write(lp); console.log(cplex); // Browser: // const cplex = await glpk.write(lp); ``` ### Response Example ```text * Problem: MyProblem * Maximize profit: + 45 chairs + 80 tables Subject To wood: + 5 chairs + 20 tables <= 400 labor: + 10 chairs + 15 tables <= 450 End ``` ``` -------------------------------- ### Solve LP/MILP with GLPK.js Source: https://context7.com/jvail/glpk.js/llms.txt Solves a linear or mixed-integer program defined by an LP object. Automatically selects simplex or branch-and-bound. Options can control solver output, presolver, and result inclusion. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); // --- LP: Maximize 0.6*x1 + 0.5*x2 --- // subject to: // x1 + 2*x2 <= 1 // 3*x1 + x2 <= 2 // x1, x2 >= 0 (default lower bound) const lp = { name: 'LP', objective: { direction: glpk.GLP_MAX, name: 'obj', vars: [ { name: 'x1', coef: 0.6 }, { name: 'x2', coef: 0.5 } ] }, subjectTo: [ { name: 'cons1', vars: [ { name: 'x1', coef: 1.0 }, { name: 'x2', coef: 2.0 } ], bnds: { type: glpk.GLP_UP, ub: 1.0, lb: 0.0 } }, { name: 'cons2', vars: [ { name: 'x1', coef: 3.0 }, { name: 'x2', coef: 1.0 } ], bnds: { type: glpk.GLP_UP, ub: 2.0, lb: 0.0 } } ] }; const result = glpk.solve(lp, { msglev: glpk.GLP_MSG_ALL, // full solver output presol: true, // use presolver rows: true // include constraint values in result }); if (result.result.status === glpk.GLP_OPT) { console.log('Optimal objective:', result.result.z); // 0.46 console.log('Variables:', result.result.vars); // { x1: 0.6, x2: 0.2 } console.log('Dual values:', result.result.dual); // { cons1: 0.1, cons2: 0.2 } console.log('Row values:', result.result.rows); // { cons1: 1.0, cons2: 2.0 } } else { console.error('No optimal solution, status:', result.result.status); } ``` -------------------------------- ### Define a Mixed-Integer LP Problem with glpk.js Source: https://context7.com/jvail/glpk.js/llms.txt Use the `LP` object to define a mixed-integer linear programming problem, including objective function, constraints, variable bounds, and specifying integer variables. Ensure GLPK is initialized before defining the problem. ```javascript import GLPK from 'glpk.js/node'; const glpk = await GLPK(); // Mixed-Integer LP: Maximize x1 + 2*x2 + 3*x3 + x4 // x4 is integer, bounded between 2 and 3 const mip = { name: 'mip', objective: { direction: glpk.GLP_MAX, // GLP_MIN for minimization name: 'obj', vars: [ { name: 'x1', coef: 1 }, { name: 'x2', coef: 2 }, { name: 'x3', coef: 3 }, { name: 'x4', coef: 1 } ] }, subjectTo: [ { name: 'c1', vars: [ { name: 'x1', coef: -1 }, { name: 'x2', coef: 1 }, { name: 'x3', coef: 1 }, { name: 'x4', coef: 10 } ], // GLP_UP: row <= ub (ub: 20) bnds: { type: glpk.GLP_UP, ub: 20, lb: 0 } }, { name: 'c2', vars: [ { name: 'x1', coef: 1 }, { name: 'x2', coef: -3 }, { name: 'x3', coef: 1 } ], bnds: { type: glpk.GLP_UP, ub: 30, lb: 0 } }, { name: 'c3', vars: [ { name: 'x2', coef: 1 }, { name: 'x4', coef: -3.5 } ], // GLP_FX: row = lb = ub (equality constraint) bnds: { type: glpk.GLP_FX, ub: 0, lb: 0 } } ], // Optional: override default bounds (default is lb=0, ub=+Inf) bounds: [ { name: 'x1', type: glpk.GLP_DB, lb: 0, ub: 40 }, // 0 <= x1 <= 40 { name: 'x4', type: glpk.GLP_DB, lb: 2, ub: 3 } // 2 <= x4 <= 3 ], // Integer variables (branch-and-bound will be used) generals: ['x4'], // Binary variables (implicitly 0/1) // binaries: ['y1', 'y2'] }; const result = glpk.solve(mip); console.log('MIP objective:', result.result.z); // 122.5 console.log('MIP vars:', result.result.vars); // { x1: 40, x2: 10.5, x3: 19.5, x4: 3 } ```