yalps
Version:
Yet another linear programming solver. (A rewrite of javascript-lp-solver.) Aims to be decently fast.
1 lines • 33.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/constraint.ts","../src/tableau.ts","../src/util.ts","../src/simplex.ts","../src/branchAndCut.ts","../src/YALPS.ts"],"sourcesContent":["export * from \"./types.js\"\nexport * from \"./constraint.js\"\nexport { solve, defaultOptions } from \"./YALPS.js\"\n","import { Constraint } from \"./types.js\"\n\n/**\n * Returns a {@link Constraint} that specifies something should be less than or equal to `value`.\n * Equivalent to `{ max: value }`.\n */\nexport const lessEq = (value: number): Constraint => ({ max: value })\n\n/**\n * Returns a {@link Constraint} that specifies something should be greater than or equal to `value`.\n * Equivalent to `{ min: value }`.\n */\nexport const greaterEq = (value: number): Constraint => ({ min: value })\n\n/**\n * Returns a {@link Constraint} that specifies something should be exactly equal to `value`.\n * Equivalent to `{ equal: value }`.\n */\nexport const equalTo = (value: number): Constraint => ({ equal: value })\n\n/**\n * Returns a {@link Constraint} that specifies something should be between `lower` and `upper` (both inclusive).\n * Equivalent to `{ min: lower, max: upper }`.\n */\nexport const inRange = (lower: number, upper: number): Constraint => ({ min: lower, max: upper })\n","import { Coefficients, Model } from \"./types.js\"\n\n// The tableau representing the problem.\n// matrix is a 2D matrix (duh) represented as a 1D array.\n// The first row, 0, is the objective row.\n// The first column, 0, is the RHS column.\n// Positions are numbered starting at the first column and ending at the last row.\n// Thus, the position of the variable in the first row is width.\nexport type Tableau = {\n readonly matrix: Float64Array\n readonly width: number\n readonly height: number\n readonly positionOfVariable: Int32Array\n readonly variableAtPosition: Int32Array\n}\n\nexport const index = (tableau: Tableau, row: number, col: number) => tableau.matrix[Math.imul(row, tableau.width) + col]\n\nexport const update = (tableau: Tableau, row: number, col: number, value: number) => {\n tableau.matrix[Math.imul(row, tableau.width) + col] = value\n}\n\nexport type Variables<VarKey = string, ConKey = string> = readonly (readonly [VarKey, Coefficients<ConKey>])[]\n\n// A tableau with some additional context.\nexport type TableauModel<VariableKey = string, ConstraintKey = string> = {\n readonly tableau: Tableau\n readonly sign: number\n readonly variables: Variables<VariableKey, ConstraintKey>\n readonly integers: readonly number[]\n}\n\nconst convertToIterable = <K, V>(\n seq: Iterable<readonly [K, V]> | ([K] extends [string] ? Readonly<Partial<Record<K, V>>> : never),\n) =>\n Symbol.iterator in seq && typeof seq[Symbol.iterator] === \"function\"\n ? seq\n : // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n (Object.entries(seq) as Iterable<readonly [K, V]>)\n\n// prettier-ignore\nconst convertToSet = <T>(set: boolean | Iterable<T> | undefined): true | Set<T> =>\n set === true ? true\n : set === false ? new Set()\n : set instanceof Set ? set\n : new Set(set)\n\nexport const tableauModel = <VarKey = string, ConKey = string>(\n model: Model<VarKey, ConKey>,\n): TableauModel<VarKey, ConKey> => {\n const { direction, objective, integers, binaries } = model\n const sign = direction === \"minimize\" ? -1.0 : 1.0\n\n const constraintsIter = convertToIterable(model.constraints)\n const variablesIter = convertToIterable(model.variables)\n const variables: Variables<VarKey, ConKey> = Array.isArray(variablesIter) ? variablesIter : Array.from(variablesIter)\n\n const binaryConstraintCol: number[] = []\n const ints: number[] = []\n if (integers != null || binaries != null) {\n const binaryVariables = convertToSet(binaries)\n const integerVariables = binaryVariables === true ? true : convertToSet(integers)\n for (let i = 1; i <= variables.length; i++) {\n const [key] = variables[i - 1]\n if (binaryVariables === true || binaryVariables.has(key)) {\n binaryConstraintCol.push(i)\n ints.push(i)\n } else if (integerVariables === true || integerVariables.has(key)) {\n ints.push(i)\n }\n }\n }\n\n const constraints = new Map<ConKey, { row: number; lower: number; upper: number }>()\n for (const [key, constraint] of constraintsIter) {\n const bounds = constraints.get(key) ?? { row: NaN, lower: -Infinity, upper: Infinity }\n bounds.lower = Math.max(bounds.lower, constraint.equal ?? constraint.min ?? -Infinity)\n bounds.upper = Math.min(bounds.upper, constraint.equal ?? constraint.max ?? Infinity)\n // if (rows.lower > rows.upper) return [\"infeasible\", NaN]\n if (!constraints.has(key)) constraints.set(key, bounds)\n }\n\n let numConstraints = 1\n for (const constraint of constraints.values()) {\n constraint.row = numConstraints\n numConstraints += (Number.isFinite(constraint.lower) ? 1 : 0) + (Number.isFinite(constraint.upper) ? 1 : 0)\n }\n const width = variables.length + 1\n const height = numConstraints + binaryConstraintCol.length\n const numVars = width + height\n const matrix = new Float64Array(width * height)\n const positionOfVariable = new Int32Array(numVars)\n const variableAtPosition = new Int32Array(numVars)\n const tableau = { matrix, width, height, positionOfVariable, variableAtPosition }\n\n for (let i = 0; i < numVars; i++) {\n positionOfVariable[i] = i\n variableAtPosition[i] = i\n }\n\n for (let c = 1; c < width; c++) {\n for (const [constraint, coef] of convertToIterable(variables[c - 1][1])) {\n if (constraint === objective) {\n update(tableau, 0, c, sign * coef)\n }\n const bounds = constraints.get(constraint)\n if (bounds != null) {\n if (Number.isFinite(bounds.upper)) {\n update(tableau, bounds.row, c, coef)\n if (Number.isFinite(bounds.lower)) {\n update(tableau, bounds.row + 1, c, -coef)\n }\n } else if (Number.isFinite(bounds.lower)) {\n update(tableau, bounds.row, c, -coef)\n }\n }\n }\n }\n\n for (const bounds of constraints.values()) {\n if (Number.isFinite(bounds.upper)) {\n update(tableau, bounds.row, 0, bounds.upper)\n if (Number.isFinite(bounds.lower)) {\n update(tableau, bounds.row + 1, 0, -bounds.lower)\n }\n } else if (Number.isFinite(bounds.lower)) {\n update(tableau, bounds.row, 0, -bounds.lower)\n }\n }\n\n for (let b = 0; b < binaryConstraintCol.length; b++) {\n const row = numConstraints + b\n update(tableau, row, 0, 1.0)\n update(tableau, row, binaryConstraintCol[b], 1.0)\n }\n\n return { tableau, sign, variables, integers: ints }\n}\n","export const roundToPrecision = (num: number, precision: number) => {\n const rounding = Math.round(1.0 / precision)\n return Math.round((num + Number.EPSILON) * rounding) / rounding\n}\n","import { Options, SolutionStatus } from \"./types.js\"\nimport { index, Tableau, update } from \"./tableau.js\"\nimport { roundToPrecision } from \"./util.js\"\n\nconst pivot = (tableau: Tableau, row: number, col: number) => {\n const quotient = index(tableau, row, col)\n const leaving = tableau.variableAtPosition[tableau.width + row]\n const entering = tableau.variableAtPosition[col]\n tableau.variableAtPosition[tableau.width + row] = entering\n tableau.variableAtPosition[col] = leaving\n tableau.positionOfVariable[leaving] = col\n tableau.positionOfVariable[entering] = tableau.width + row\n\n const nonZeroColumns: number[] = []\n // (1 / quotient) * R_pivot -> R_pivot\n for (let c = 0; c < tableau.width; c++) {\n const value = index(tableau, row, c)\n if (Math.abs(value) > 1e-16) {\n update(tableau, row, c, value / quotient)\n nonZeroColumns.push(c)\n } else {\n update(tableau, row, c, 0.0)\n }\n }\n update(tableau, row, col, 1.0 / quotient)\n\n // -M[r, col] * R_pivot + R_r -> R_r\n for (let r = 0; r < tableau.height; r++) {\n if (r === row) continue\n const coef = index(tableau, r, col)\n if (Math.abs(coef) > 1e-16) {\n for (let i = 0; i < nonZeroColumns.length; i++) {\n const c = nonZeroColumns[i]\n update(tableau, r, c, index(tableau, r, c) - coef * index(tableau, row, c))\n }\n update(tableau, r, col, -coef / quotient)\n }\n }\n}\n\ntype PivotHistory = (readonly [row: number, col: number])[]\n\n// Checks if the simplex method has encountered a cycle.\nconst hasCycle = (history: PivotHistory, tableau: Tableau, row: number, col: number) => {\n // This whole function seems somewhat inefficient,\n // but there was no? noticeable impact in the benchmarks.\n history.push([tableau.variableAtPosition[tableau.width + row], tableau.variableAtPosition[col]])\n // the minimum length of a cycle is 6\n for (let length = 6; length <= Math.trunc(history.length / 2); length++) {\n let cycle = true\n for (let i = 0; i < length; i++) {\n const item = history.length - 1 - i\n const [row1, col1] = history[item]\n const [row2, col2] = history[item - length]\n if (row1 !== row2 || col1 !== col2) {\n cycle = false\n break\n }\n }\n if (cycle) return true\n }\n return false\n}\n\n// Finds the optimal solution given some basic feasible solution.\nconst phase2 = (tableau: Tableau, options: Required<Options>): [SolutionStatus, number] => {\n const pivotHistory: PivotHistory = []\n const { precision, maxPivots, checkCycles } = options\n for (let iter = 0; iter < maxPivots; iter++) {\n // Find the entering column/variable\n let col = 0\n let value = precision\n for (let c = 1; c < tableau.width; c++) {\n const reducedCost = index(tableau, 0, c)\n if (reducedCost > value) {\n value = reducedCost\n col = c\n }\n }\n if (col === 0) return [\"optimal\", roundToPrecision(index(tableau, 0, 0), precision)]\n\n // Find the leaving row/variable\n let row = 0\n let minRatio = Infinity\n for (let r = 1; r < tableau.height; r++) {\n const value = index(tableau, r, col)\n if (value <= precision) continue // pivot entry must be positive\n const rhs = index(tableau, r, 0)\n const ratio = rhs / value\n if (ratio < minRatio) {\n row = r\n minRatio = ratio\n if (ratio <= precision) break // ratio is 0, lowest possible\n }\n }\n if (row === 0) return [\"unbounded\", col]\n\n if (checkCycles && hasCycle(pivotHistory, tableau, row, col)) return [\"cycled\", NaN]\n\n pivot(tableau, row, col)\n }\n return [\"cycled\", NaN]\n}\n\n// Transforms a tableau into a basic feasible solution.\nconst phase1 = (tableau: Tableau, options: Required<Options>): [SolutionStatus, number] => {\n const pivotHistory: PivotHistory = []\n const { precision, maxPivots, checkCycles } = options\n for (let iter = 0; iter < maxPivots; iter++) {\n // Find the leaving row/variable\n let row = 0\n let rhs = -precision\n for (let r = 1; r < tableau.height; r++) {\n const value = index(tableau, r, 0)\n if (value < rhs) {\n rhs = value\n row = r\n }\n }\n if (row === 0) return phase2(tableau, options)\n\n // Find the entering column/variable\n let col = 0\n let maxRatio = -Infinity\n for (let c = 1; c < tableau.width; c++) {\n const coefficient = index(tableau, row, c)\n if (coefficient < -precision) {\n const ratio = -index(tableau, 0, c) / coefficient\n if (ratio > maxRatio) {\n maxRatio = ratio\n col = c\n }\n }\n }\n if (col === 0) return [\"infeasible\", NaN]\n\n if (checkCycles && hasCycle(pivotHistory, tableau, row, col)) return [\"cycled\", NaN]\n\n pivot(tableau, row, col)\n }\n return [\"cycled\", NaN]\n}\n\nexport { phase1 as simplex }\n","import { Options, SolutionStatus } from \"./types.js\"\nimport { index, Tableau, TableauModel } from \"./tableau.js\"\nimport { simplex } from \"./simplex.js\"\nimport Heap from \"heap\"\n\ntype Buffer = {\n readonly matrix: Float64Array\n readonly positionOfVariable: Int32Array\n readonly variableAtPosition: Int32Array\n}\n\nconst buffer = (matrixLength: number, posVarLength: number): Buffer => ({\n matrix: new Float64Array(matrixLength),\n positionOfVariable: new Int32Array(posVarLength),\n variableAtPosition: new Int32Array(posVarLength),\n})\n\ntype Cut = readonly [sign: number, variable: number, value: number]\ntype Branch = readonly [eval: number, cuts: readonly Cut[]]\n\n// Creates a new tableau with additional cut constraints from a buffer.\nconst applyCuts = (\n tableau: Tableau,\n { matrix, positionOfVariable, variableAtPosition }: Buffer,\n cuts: readonly Cut[],\n): Tableau => {\n const { width, height } = tableau\n matrix.set(tableau.matrix)\n for (let i = 0; i < cuts.length; i++) {\n const [sign, variable, value] = cuts[i]\n const r = (height + i) * width\n const pos = tableau.positionOfVariable[variable]\n if (pos < width) {\n matrix[r] = sign * value\n matrix.fill(0.0, r + 1, r + width)\n matrix[r + pos] = sign\n } else {\n const row = (pos - width) * width\n matrix[r] = sign * (value - matrix[row])\n for (let c = 1; c < width; c++) {\n matrix[r + c] = -sign * matrix[row + c]\n }\n }\n }\n\n positionOfVariable.set(tableau.positionOfVariable)\n variableAtPosition.set(tableau.variableAtPosition)\n const length = width + height + cuts.length\n for (let i = width + height; i < length; i++) {\n positionOfVariable[i] = i\n variableAtPosition[i] = i\n }\n\n return {\n matrix: matrix.subarray(0, tableau.matrix.length + width * cuts.length),\n width,\n height: height + cuts.length,\n positionOfVariable: positionOfVariable.subarray(0, length),\n variableAtPosition: variableAtPosition.subarray(0, length),\n }\n}\n\n// Finds the integer variable with the most fractional value.\nconst mostFractionalVar = (\n tableau: Tableau,\n intVars: readonly number[],\n): [variable: number, value: number, frac: number] => {\n let highestFrac = 0.0\n let variable = 0\n let value = 0.0\n for (let i = 0; i < intVars.length; i++) {\n const intVar = intVars[i]\n const row = tableau.positionOfVariable[intVar] - tableau.width\n if (row < 0) continue\n\n const val = index(tableau, row, 0)\n const frac = Math.abs(val - Math.round(val))\n if (frac > highestFrac) {\n highestFrac = frac\n variable = intVar\n value = val\n }\n }\n return [variable, value, highestFrac]\n}\n\n// Runs the branch and cut algorithm to solve an integer problem.\n// Requires the non-integer solution as input.\nexport const branchAndCut = <VarKey, ConKey>(\n tabmod: TableauModel<VarKey, ConKey>,\n initResult: number,\n options: Required<Options>,\n): [TableauModel<VarKey, ConKey>, SolutionStatus, number] => {\n const { tableau, sign, integers } = tabmod\n const { precision, maxIterations, tolerance, timeout } = options\n const [initVariable, initValue, initFrac] = mostFractionalVar(tableau, integers)\n // Wow, the initial solution is integer\n if (initFrac <= precision) return [tabmod, \"optimal\", initResult]\n\n const branches = new Heap<Branch>((x, y) => x[0] - y[0])\n branches.push([initResult, [[-1, initVariable, Math.ceil(initValue)]]])\n branches.push([initResult, [[1, initVariable, Math.floor(initValue)]]])\n\n // Set aside arrays/buffers to be reused over the course of the algorithm.\n // One set of buffers stores the state of the current best solution.\n // The other is used to solve the current candidate solution.\n // The two buffers are \"swapped\" once a new best solution is found.\n const maxExtraRows = integers.length * 2\n const matrixLength = tableau.matrix.length + maxExtraRows * tableau.width\n const posVarLength = tableau.positionOfVariable.length + maxExtraRows\n let candidateBuffer = buffer(matrixLength, posVarLength)\n let solutionBuffer = buffer(matrixLength, posVarLength)\n\n const optimalThreshold = initResult * (1.0 - sign * tolerance)\n const stopTime = timeout + Date.now()\n let timedout = Date.now() >= stopTime // in case options.timeout <= 0\n let solutionFound = false\n let bestEval = Infinity\n let bestTableau = tableau\n let iter = 0\n\n while (iter < maxIterations && !branches.empty() && bestEval >= optimalThreshold && !timedout) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const [relaxedEval, cuts] = branches.pop()!\n if (relaxedEval > bestEval) break // the remaining branches are worse than the current best solution\n\n const currentTableau = applyCuts(tableau, candidateBuffer, cuts)\n const [status, result] = simplex(currentTableau, options)\n // The initial tableau is not unbounded and adding more cuts/constraints cannot make it become unbounded\n // assert(status !== \"unbounded\")\n if (status === \"optimal\" && result < bestEval) {\n const [variable, value, frac] = mostFractionalVar(currentTableau, integers)\n if (frac <= precision) {\n // The solution is integer\n solutionFound = true\n bestEval = result\n bestTableau = currentTableau\n const temp = solutionBuffer\n solutionBuffer = candidateBuffer\n candidateBuffer = temp\n } else {\n const cutsUpper: Cut[] = []\n const cutsLower: Cut[] = []\n for (let i = 0; i < cuts.length; i++) {\n const cut = cuts[i]\n const [dir, v] = cut\n if (v === variable) {\n if (dir < 0) {\n cutsLower.push(cut)\n } else {\n cutsUpper.push(cut)\n }\n } else {\n cutsUpper.push(cut)\n cutsLower.push(cut)\n }\n }\n cutsLower.push([1, variable, Math.floor(value)])\n cutsUpper.push([-1, variable, Math.ceil(value)])\n branches.push([result, cutsUpper])\n branches.push([result, cutsLower])\n }\n }\n // Otherwise, this branch's result is worse than the current best solution.\n // This could be because this branch is infeasible or cycled.\n // Either way, skip this branch and see if any other branches have a valid, better solution.\n timedout = Date.now() >= stopTime\n iter++\n }\n\n // Did the solver \"timeout\"?\n const unfinished = (timedout || iter >= maxIterations) && !branches.empty() && bestEval >= optimalThreshold\n\n // prettier-ignore\n const status =\n unfinished ? \"timedout\"\n : !solutionFound ? \"infeasible\"\n : \"optimal\"\n\n return [{ ...tabmod, tableau: bestTableau }, status, solutionFound ? bestEval : NaN]\n}\n","import { Model, Options, SolutionStatus, Solution } from \"./types.js\"\nimport { index, tableauModel, TableauModel } from \"./tableau.js\"\nimport { roundToPrecision } from \"./util.js\"\nimport { simplex } from \"./simplex.js\"\nimport { branchAndCut } from \"./branchAndCut.js\"\n\n// Creates a solution object representing the optimal solution (if any).\nconst solution = <VarKey, ConKey>(\n { tableau, sign, variables: vars }: TableauModel<VarKey, ConKey>,\n status: SolutionStatus,\n result: number,\n { precision, includeZeroVariables }: Required<Options>,\n): Solution<VarKey> => {\n if (status === \"optimal\" || (status === \"timedout\" && !Number.isNaN(result))) {\n const variables: [VarKey, number][] = []\n for (let i = 0; i < vars.length; i++) {\n const [variable] = vars[i]\n const row = tableau.positionOfVariable[i + 1] - tableau.width\n const value = row >= 0 ? index(tableau, row, 0) : 0.0\n if (value > precision) {\n variables.push([variable, roundToPrecision(value, precision)])\n } else if (includeZeroVariables) {\n variables.push([variable, 0.0])\n }\n }\n return {\n status,\n result: -sign * result,\n variables,\n }\n } else if (status === \"unbounded\") {\n const variable = tableau.variableAtPosition[result] - 1\n return {\n status: \"unbounded\",\n result: sign * Infinity,\n // prettier-ignore\n variables:\n (0 <= variable && variable < vars.length)\n ? [[vars[variable][0], Infinity]]\n : [],\n }\n } else {\n // infeasible | cycled | (timedout and result is NaN)\n return {\n status,\n result: NaN,\n variables: [],\n }\n }\n}\n\nconst defaultOptionValues: Required<Options> = {\n precision: 1e-8,\n checkCycles: false,\n maxPivots: 8192,\n tolerance: 0,\n timeout: Infinity,\n maxIterations: 32768,\n includeZeroVariables: false,\n}\n\n/**\n * The default options used by the solver.\n */\nexport const defaultOptions: Required<Options> = { ...defaultOptionValues }\n\n/**\n * Runs the solver on the given model and using the given options (if any).\n * @see {@link Model} on how to specify/create the model.\n * @see {@link Options} for the kinds of options available.\n * @see {@link Solution} for more detailed information on what is returned.\n */\nexport const solve = <VarKey = string, ConKey = string>(\n model: Model<VarKey, ConKey>,\n options?: Options,\n): Solution<VarKey> => {\n const tabmod = tableauModel(model)\n const opt = { ...defaultOptionValues, ...options }\n const [status, result] = simplex(tabmod.tableau, opt)\n\n if (tabmod.integers.length === 0 || status !== \"optimal\") {\n // If a non-integer problem, return the simplex result.\n // Otherwise, the problem has integer variables, but the initial solution is either:\n // 1) unbounded | infeasible => all branches will also be unbounded | infeasible\n // 2) cycled => cannot get an initial solution, return invalid solution\n return solution(tabmod, status, result, opt)\n } else {\n // Integer problem and an optimal non-integer solution was found\n const [intTabmod, intStatus, intResult] = branchAndCut(tabmod, result, opt)\n return solution(intTabmod, intStatus, intResult, opt)\n }\n}\n"],"mappings":"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","names":["value","Heap","status"]}