UNPKG

@uandi/javascript-lp-solver

Version:

Easy to use, JSON oriented Linear Programming and Mixed Int. Programming Solver

175 lines (150 loc) 5.9 kB
/*global describe*/ /*global require*/ /*global module*/ /*global it*/ /*global console*/ /*global process*/ //------------------------------------------------------------------- // SimplexJS // https://github.com/ // An Object-Oriented Linear Programming Solver // // By Justin Wolcott (c) // Licensed under the MIT License. //------------------------------------------------------------------- var Tableau = require("./Tableau/index.js"); var Model = require("./Model"); var branchAndCut = require("./Tableau/branchAndCut"); var expressions = require("./expressions.js"); var validation = require("./Validation"); var Constraint = expressions.Constraint; var Variable = expressions.Variable; var Numeral = expressions.Numeral; var Term = expressions.Term; // Place everything under the Solver Name Space var Solver = function () { "use strict"; this.Model = Model; this.branchAndCut = branchAndCut; this.Constraint = Constraint; this.Variable = Variable; this.Numeral = Numeral; this.Term = Term; this.Tableau = Tableau; this.lastSolvedModel = null; /************************************************************* * Method: Solve * Scope: Public: * Agruments: * model: The model we want solver to operate on * precision: If we're solving a MILP, how tight * do we want to define an integer, given * that 20.000000000000001 is not an integer. * (defaults to 1e-9) * full: *get better description* * validate: if left blank, it will get ignored; otherwise * it will run the model through all validation * functions in the *Validate* module **************************************************************/ this.Solve = function (model, precision, full, validate) { // Run our validations on the model // if the model doesn't have a validate // attribute set to false if(validate){ for(var test in validation){ model = validation[test](model); } } // Make sure we at least have a model if (!model) { throw new Error("Solver requires a model to operate on"); } if (model instanceof Model === false) { model = new Model(precision).loadJson(model); } var solution = model.solve(); this.lastSolvedModel = model; solution.solutionSet = solution.generateSolutionSet(); // If the user asks for a full breakdown // of the tableau (e.g. full === true) // this will return it if (full) { return solution; } else { // Otherwise; give the user the bare // minimum of info necessary to carry on var store = {}; // 1.) Add in feasibility to store; store.feasible = solution.feasible; // 2.) Add in the objective value store.result = solution.evaluation; store.bounded = solution.bounded; // 3.) Load all of the variable values Object.keys(solution.solutionSet) .map(function (d) { store[d] = solution.solutionSet[d]; }); return store; } }; /************************************************************* * Method: ReformatLP * Scope: Public: * Agruments: model: The model we want solver to operate on * Purpose: Convert a friendly JSON model into a model for a * real solving library...in this case * lp_solver **************************************************************/ this.ReformatLP = require("./Reformat"); /************************************************************* * Method: MultiObjective * Scope: Public: * Agruments: * model: The model we want solver to operate on * detail: if false, or undefined; it will return the * result of using the mid-point formula; otherwise * it will return an object containing: * * 1. The results from the mid point formula * 2. The solution for each objective solved * in isolation (pareto) * 3. The min and max of each variable along * the frontier of the polytope (ranges) * Purpose: Solve a model with multiple objective functions. * Since a potential infinite number of solutions exist * this naively returns the mid-point between * * Note: The model has to be changed a little to work with this. * Before an *opType* was required. No more. The objective * attribute of the model is now an object instead of a * string. * * *EXAMPLE MODEL* * * model = { * optimize: {scotch: "max", soda: "max"}, * constraints: {fluid: {equal: 100}}, * variables: { * scotch: {fluid: 1, scotch: 1}, * soda: {fluid: 1, soda: 1} * } * } * **************************************************************/ this.MultiObjective = function(model){ return require("./Polyopt")(this, model); }; }; var define = define || undefined; var window = window || undefined; // If the project is loading through require.js, use `define` and exit if (typeof define === "function") { define([], function () { return new Solver(); }); // If the project doesn't see define, but sees window, put solver on window } else if (typeof window === "object"){ window.solver = new Solver(); } // Ensure that its available in node.js env module.exports = new Solver();