{"id":14384748,"url":"https://github.com/JWally/jsLPSolver","last_synced_at":"2025-08-23T17:33:31.519Z","repository":{"id":10273540,"uuid":"12387548","full_name":"JWally/jsLPSolver","owner":"JWally","description":"Simple OOP javaScript library to solve linear programs, and mixed integer linear programs","archived":false,"fork":false,"pushed_at":"2023-05-05T13:47:27.000Z","size":8235,"stargazers_count":432,"open_issues_count":33,"forks_count":68,"subscribers_count":28,"default_branch":"master","last_synced_at":"2025-08-21T11:02:23.665Z","etag":null,"topics":["constraint-optimization","integer-linear-programming","linear-programming","simplex-algorithm"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JWally.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2013-08-26T19:16:18.000Z","updated_at":"2025-07-09T18:10:33.000Z","dependencies_parsed_at":"2022-09-03T06:22:23.099Z","dependency_job_id":"7c8d9845-4920-4a10-b9c5-15d9a6d6949b","html_url":"https://github.com/JWally/jsLPSolver","commit_stats":{"total_commits":288,"total_committers":17,"mean_commits":"16.941176470588236","dds":0.625,"last_synced_commit":"2f067bc134d720f1900e291f4ef4d8b004599904"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/JWally/jsLPSolver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JWally%2FjsLPSolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JWally%2FjsLPSolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JWally%2FjsLPSolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JWally%2FjsLPSolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JWally","download_url":"https://codeload.github.com/JWally/jsLPSolver/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JWally%2FjsLPSolver/sbom","scorecard":{"id":69366,"data":{"date":"2025-08-11","repo":{"name":"github.com/JWally/jsLPSolver","commit":"e0c0e73f00ab795d6f55af2773b1fc0282c04068"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/27 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: The Unlicense: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-15T03:28:05.683Z","repository_id":10273540,"created_at":"2025-08-15T03:28:05.683Z","updated_at":"2025-08-15T03:28:05.683Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271745736,"owners_count":24813525,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constraint-optimization","integer-linear-programming","linear-programming","simplex-algorithm"],"created_at":"2024-08-28T18:01:38.181Z","updated_at":"2025-08-23T17:33:29.812Z","avatar_url":"https://github.com/JWally.png","language":"JavaScript","readme":"jsLPSolver\n==========\n[A linear programming solver for the rest of us!](https://youtu.be/LbfMmCf5-ds?t=51)\n\n\nWhat Can I do with it?\n-----------------------\n\nYou can solve problems that fit the following fact pattern like this one\nfrom [this](http://math.stackexchange.com/questions/59429/berlin-airlift-linear-optimization-problem) site.\n\n\u003eOn June 24, 1948, the former Soviet Union blocked all land and water routes through East Germany to Berlin.\n\u003eA gigantic airlift was organized using American and British planes to supply food, clothing and other supplies\n\u003eto more than 2 million people in West Berlin.\n\u003e\n\u003eThe cargo capacity was 30,000 cubic feet for an American plane and 20,000 cubic feet for a British plane.\n\u003eTo break the Soviet blockade, the Western Allies had to maximize cargo capacity,\n\u003ebut were subject to the following restrictions: No more than 44 planes could be used. The larger American planes required 16\n\u003epersonnel per flight; double that of the requirement for the British planes. The total number of personnel\n\u003eavailable could not exceed 512. The cost of an American flight was $9000 and the cost of a British flight was $5000.\n\u003eThe total weekly costs could note exceed $300,000.\n\u003eFind the number of American and British planes that were used to maximize cargo capacity.\n\n\n\nSo How Would I Do This?\n-----------------------\nPart of the reason I built this library is that I wanted to do as little thinking / setup as possible\nto solve the actual problem. Instead of tinkering with arrays to solve this problem, you would create a\nmodel in a JavaScript object, and solve it through the solver's `solve` function; like this:\n\n### Install:\n\n\n(in Node)\n```\nnpm install javascript-lp-solver --save\n```\n\n(in browser through CDN)\n```html\n\u003cscript src=\"https://unpkg.com/javascript-lp-solver/prod/solver.js\"\u003e\u003c/script\u003e\n```\n\n(webpack)\n```javascript\nconst webpack = require('webpack'); //to access built-in plugins\n\nmodule.exports = {\n        \"mode\": \"development\",\n        \"plugins\": [\n            new webpack.IgnorePlugin(/(fs|child_process)/),\n        ]\n}\n```\n\n### Use:\n\n```javascript\nvar solver = require(\"./src/solver\"),\n  results,\n  model = {\n    \"optimize\": \"capacity\",\n    \"opType\": \"max\",\n    \"constraints\": {\n        \"plane\": {\"max\": 44},\n        \"person\": {\"max\": 512},\n        \"cost\": {\"max\": 300000}\n    },\n    \"variables\": {\n        \"brit\": {\n            \"capacity\": 20000,\n            \"plane\": 1,\n            \"person\": 8,\n            \"cost\": 5000\n        },\n        \"yank\": {\n            \"capacity\": 30000,\n            \"plane\": 1,\n            \"person\": 16,\n            \"cost\": 9000\n        }\n    },\n};\n\nresults = solver.Solve(model);\nconsole.log(results);\n```\n\nwhich should yield the following:\n```\n{feasible: true, brit: 24, yank: 20, result: 1080000}\n```\n\nWhat If I Want Only Integers\n--------------------\n\nSay you live in the real world and partial results aren't realistic, too messy, or generally unsafe.\n\n\u003e You run a small custom furniture shop and make custom tables and dressers.\n\u003e\n\u003e Each week you're limited to 300 square feet of wood, 110 hours of labor,\n\u003e and 400 square feet of storage.\n\u003e\n\u003e A table uses 30sf of wood, 5 hours of labor, requires 30sf of storage and has a\n\u003e gross profit of $1,200. A dresser uses 20sf of wood, 10 hours of work to put\n\u003e together, requires 50 square feet to store and has a gross profit of $1,600.\n\u003e\n\u003e How much of each do you produce to maximize profit, given that partial furniture\n\u003e aren't allowed in this dumb world problem?\n\n```javascript\nvar solver = require(\"./src/solver\"),\n    model = {\n        \"optimize\": \"profit\",\n        \"opType\": \"max\",\n        \"constraints\": {\n            \"wood\": {\"max\": 300},\n            \"labor\": {\"max\": 110},\n            \"storage\": {\"max\": 400}\n        },\n        \"variables\": {\n            \"table\": {\"wood\": 30, \"labor\": 5, \"profit\": 1200, \"table\": 1, \"storage\": 30},\n            \"dresser\": {\"wood\": 20, \"labor\": 10, \"profit\": 1600, \"dresser\": 1, \"storage\": 50}\n        },\n        \"ints\": {\"table\": 1, \"dresser\": 1}\n    }\n    \nconsole.log(solver.Solve(model));\n// {feasible: true, result: 1440-0, table: 8, dresser: 3}\n```\n\nMy problem is HUGE. Can I do this async or something? \n--------------------\n\nYes! Or something!\n\nSo its not truly async, but an instance of solver can be easily(?) put in an instance of a web worker.\n\n*worker.js*\n```javascript\n\n// n.b. Solver connects itself to the global 'self'\n// if its available...\n//\nimportScripts(\"/prod/solver.js\");\n\nonmessage = function(d){\n    var results = solver.Solve(d.data);\n    postMessage(results);\n};\n```\n\n*main.html*\n```javascript\n\n    var w = new Worker(\"./worker.js\");\n\n    w.onmessage = function(d){\n        //\n        // do something fun / exciting with our results!\n        //\n        console.log(d);\n    }\n\n    w.postMessage(lp_model);\n```\n\nHow Fast Can It Go?\n---------------------\n\nRandom selection of problems of \"some\" size / interest:\n\n```\n-----------------\n-----------------\nLargeFarmMIP [ 100  variables, 35  constraints,  100  integers ]\njsLPSolver: 16.475ms\n\n\n-----------------\n-----------------\nMonster Problem [ 552  variables, 600  constraints,  0  integers ]\njsLPSolver: 18.142ms\n\n\n-----------------\n-----------------\nmonster_II [ 924  variables, 888  constraints,  112  integers ]\njsLPSolver: 308.026ms\n\n\n-----------------\n-----------------\nFancy Stock Cutting Problem [ 31  variables, 5  constraints,  31  integers ]\njsLPSolver: 1.396ms\n\n\n-----------------\n-----------------\nVendor Selection [ 1640  variables, 1641  constraints,  0  integers ]\njsLPSolver: 1222.659ms\n\n\n``` \n\nNeat! What else can I do with it?\n\n\nAPI / Guide\n===============\n\nBelow is my first pass at describing the various parts of the model, what they do, and other miscellaneous options that might not\nbe super intuitive.\n\nAs much as possible, I'm trying to make all of the options / functions accessible by changing the JSON model. To me (maybe incorrectly),\nit's easier to be able to just call one method to do everything based on the model its given instead of having to hit seperate functions\nexposed on the solver itself.\n\n#### optimize\n\nThis tells the model (wait for it) what to optimize (minimize or maximize). Typically (honestly, always) the thing you're optimizing is an attribute\nof a variable. For example, `profit` might be a variable attribute you want to maximize. In this case, your model would look like this:\n\n```json\n    {\n        \"optimize\": \"profit\",\n        \"opType\": \"max\",\n    }\n```\n\n_MULTI OBJECTIVE OPTIMIZATION_: This is kind of a throwaway function I added because I needed it for something. I don't know if there's a better way to do this, or if it even makes sense, so please take this with a grain of salt.\n\nSay you have a problem where you want to eat as much \"bacon\", \"cheddar cheese\", and \"french fries\" as possible. To do this, set the \"optimize\" attribute of the model like this:\n\n```json\n    \"optimize\": {\n        \"bacon\": \"max\",\n        \"cheddar cheese\": \"max\",\n        \"french fries\": \"max\"\n    }\n```\n\nThis will return a result where no single objective can be improved without hurting at least one other objective. It also returns the results of the \"child\" optimization problems \n\n#### opType\n\nThis tells the solver how to optimize your problem. Acceptable options are \"min\" for minimize and \"max\" for maximize.\n\n#### variables\n\nThese are the inputs of your problem. For the word problem:\n\n\u003eHow many chairs, tables, and desks do you need to produce given that a chair requires ...\n\n...chairs, tables, and desks are your variables. You can assign attributes to the variables (size, cost, weight, etc) that you can use to constrain the problem.\n\nOn your model, your variables would look like this:\n\n```json\n        \"variables\": {\n            \"table\": {\"wood\": 30, \"labor\": 5, \"profit\": 1200, \"storage\": 30},\n            \"dresser\": {\"wood\": 20, \"labor\": 10, \"profit\": 1600, \"storage\": 50}\n        },\n```\n\n#### constraints\n\nReal world problems don't allow you to use an unlimited number of resources (sad). In order to solve problems like \n\n\u003eMaximize Profit...\n\nwhere resources are limited; constraints come into play. Here is where you put them. (In a normal LP tableau, these are the inequalities).\n\nUsing the above example, say you had at most 300 units of wood, 110 units of labour, and 400 units of storage. To represent this in JSON format, you\nwould set it up like this:\n\n```json\n    \"constraints\": {\n        \"wood\": {\"max\": 300},\n        \"labor\": {\"max\": 110},\n        \"storage\": {\"max\": 400}\n    },\n```\n\n...where for the first constraint, \"wood\" is the attribute you're setting a constraint on with a \"maximum\" of 300 units used to solve the the problem. Other options for constraints are \"min\" (minimum) and \"equal\" (equal to).\n\n#### options\n\nThis is a catch-all place to put additional options on the model for the Solver to work with in an attempt to not clutter the \"core\" of the model too much.\n\n#### options.timeout (default: none)\n\nThis option is how many milliseconds you want to allow for the solver to try and solve the model you're running. You set it like this:\n\n```json\n\"options\": {\n    \"timeout\": 10000\n}\n```\n\nN.B. currently, it only works for mixed-integer linear programs\n\n#### options.tolerance (default: 0)\n\nFor large scale integer problems the solving process can take increasingly long. However, oftentimes the solution to these problems does not have to be the absolute best possible solution, but rather a solution relatively close to the optimal one. In these cases, a variable called tolerance can be specified in the model object. The value assigned to the tolerance variable states that the solver should stop the solution process when the best solution found is within {{options.tolerance}}% of the best theoretical objective value.\n\nIt is set up like this:\n\n```json\n\"options\": {\n    \"tolerance\": 0.05\n}\n```\n\n#### options.exitOnCycles  (default: true)\n\nExits when cycles detected\n\nExternal Solver Integration\n===============================\n\n(n.b. this is still very much in progress and subject to change...)\n\nBasically I want to be able to work with \"professional-grade\" solver libraries through jsLPSolver; without incorporating hard dependencies / binary builds / etc.\n\n\n## lpsolve\n\nTo use, incorporate the following onto your model:\n\n```json\n    \"external\": {\n        \"solver\": \"lpsolve\",\n        \"binPath\": \"C:/lpsolve/lp_solve.exe\",\n        \"tempName\": \"C:/temp/out.txt\",\n        \"args\": [\n            \"-s2\",\n            \"-timeout\",\n            240\n        ]\n    }\n```\n\nBasically, its doing the following:\n\n1. Convert your model to something lpsolve can use\n2. Saves your model to a temporary file (hence the `tempName` attribute)\n3. Runs everything through a command line (`require(\"child_process\").execFile`) against the lpsolve executable (binPath) with whatever arguments you need (args)\n4. Scrubs the results\n5. Returns a JSON object with the results\n\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJWally%2FjsLPSolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJWally%2FjsLPSolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJWally%2FjsLPSolver/lists"}