From a58cd87b09d32039e9c0d0757dab3d0252dc19f9 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 23 May 2022 18:03:03 +0200 Subject: [PATCH 1/6] fix: close #11 --- src/getShortestPath.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/getShortestPath.ts b/src/getShortestPath.ts index f883cde..c8a69a5 100644 --- a/src/getShortestPath.ts +++ b/src/getShortestPath.ts @@ -34,7 +34,7 @@ export function getShortestPath(options: GetShortestPathOptions) { let sink = -1; let delta = 0; let curColumn = currUnAssCol; - let shortestPathCost = getArrayOfInfinity(nbRows); + let shortestPathCost = new Array(nbRows).fill(Number.POSITIVE_INFINITY); while (sink === -1) { scannedColumns[curColumn] = 1; let minVal = Number.POSITIVE_INFINITY; @@ -92,11 +92,3 @@ export function getShortestPath(options: GetShortestPathOptions) { dualVariableForRows, }; } - -function getArrayOfInfinity(nbElements = 1, value = Number.POSITIVE_INFINITY) { - const array = new Array(nbElements); - for (let i = 0; i < nbElements; i++) { - array[i] = value; - } - return array; -} From 12a98937cfe83f90bc8b757b68c8c8f29857e27e Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 23 May 2022 18:04:07 +0200 Subject: [PATCH 2/6] fix: close #12 --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3140894..72f5c67 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,16 @@ import linearSumAssignment from 'linear-sum-assignment'; * there is one more value in the experimental values, so one of * them will be not assigned. **/ -const xValueExperimental = [1, 2, 3, 4, 5, 7]; -const xValuePredicted = [3.1, 1.1, 1.9, 3.99, 5.2]; +const experimental = [1, 2, 3, 4, 5, 7]; +const predicted = [3.1, 1.1, 1.9, 3.99, 5.2]; /** - * We will compute a cost matrix where xValueExperimental are - * rows and xValuePredicted in columns. + * We will compute a cost matrix where experimental are + * rows and predicted in columns. * In this case we will look for the closest peak for each experimental peak value. **/ -const diff = xValueExperimental.map((experimental) => { - return xValuePredicted.map((predicted) => { +const diff = experimental.map((experimental) => { + return predicted.map((predicted) => { return Math.abs(predicted - experimental); }); }); @@ -60,11 +60,11 @@ console.log(result); */ ``` - `rowAssignments` contains the index of the column assigned to each element in the rows (xValueExperimental). So the first element in xValueExperimental array is assigned to the second element of xValuePredicted. + `rowAssignments` contains the index of the column assigned to each element in the rows (experimental). So the first element in experimental array is assigned to the second element of predicted. `columnAssignments` contains the index of the row assigned to each element in the columns. So the first element in - xValuePredicted is assigned to third element in - xValueExperimental. + predicted is assigned to third element in + experimental. `dualVariableForColumns` and `dualVariableForRows` are the Lagrange multipliers or dual variables. `gain` the sum of the elements in the cost matrix. ## License From b6935ac8fc0361b958a935ea54422bc0ecf373d6 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 23 May 2022 18:13:34 +0200 Subject: [PATCH 3/6] fix: close #15 --- package-lock.json | 103 +++++++++++++++++++++++++++++++++++++++-- package.json | 4 +- src/getShortestPath.ts | 4 +- 3 files changed, 104 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 536d14e..ebdf25e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { - "name": "linearSumAssignment", + "name": "linear-sum-assignment", "version": "1.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "linearSumAssignment", + "name": "linear-sum-assignment", "version": "1.0.3", "license": "MIT", "dependencies": { "cheminfo-types": "^1.1.0", "install": "^0.13.0", "ml-array-sequential-fill": "^1.1.8", - "ml-matrix": "^6.10.0" + "ml-matrix": "^6.10.0", + "ml-spectra-processing": "^11.6.0" }, "devDependencies": { "@types/jest": "^27.5.0", @@ -1772,6 +1773,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2024,6 +2030,11 @@ "node": ">= 8" } }, + "node_modules/d3-array": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-0.7.1.tgz", + "integrity": "sha1-oyHCFVhFnZlOtK1HtHgkDmSTOUI=" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2819,6 +2830,11 @@ "bser": "2.1.1" } }, + "node_modules/fft.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fft.js/-/fft.js-4.0.4.tgz", + "integrity": "sha512-f9c00hphOgeQTlDyavwTtu6RiK8AIFjD6+jvXkNkpeQ7rirK3uFWVpalkoS4LAwbdX7mfZ8aoBfFVQX1Re/8aw==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4672,6 +4688,11 @@ "tmpl": "1.0.5" } }, + "node_modules/median-quickselect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/median-quickselect/-/median-quickselect-1.0.1.tgz", + "integrity": "sha1-3jQIA1pbLwQ4o5uZiT+vPn1hd/g=" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4772,6 +4793,26 @@ "ml-array-rescale": "^1.3.7" } }, + "node_modules/ml-spectra-processing": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/ml-spectra-processing/-/ml-spectra-processing-11.6.0.tgz", + "integrity": "sha512-jUtNkcUIH+M091Ttf9JvtIYTxhgmjgudexHTSUP1y7yYrLkIEMUbqYYE9L5gLDoawrm8+BYa50Ke1JV47qGD0Q==", + "dependencies": { + "binary-search": "^1.3.6", + "cheminfo-types": "^1.1.0", + "fft.js": "^4.0.4", + "is-any-array": "^2.0.0", + "median-quickselect": "^1.0.1", + "ml-matrix": "^6.10.0", + "ml-xsadd": "^2.0.0", + "spline-interpolator": "^1.0.0" + } + }, + "node_modules/ml-xsadd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-xsadd/-/ml-xsadd-2.0.0.tgz", + "integrity": "sha512-VoAYUqmPRmzKbbqRejjqceGFp3VF81Qe8XXFGU0UXLxB7Mf4GGvyGq5Qn3k4AiQgDEV6WzobqlPOd+j0+m6IrA==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5510,6 +5551,14 @@ "dev": true, "peer": true }, + "node_modules/spline-interpolator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spline-interpolator/-/spline-interpolator-1.0.0.tgz", + "integrity": "sha512-s8lowgsWE5wjHGEsk/4VADp7xAHw+pNy3OGp96fYjVTwLSx/83+BBmTFP2wZDRM0kj45q8zSyOV5fUcGn4hLEw==", + "dependencies": { + "d3-array": "^0.7.1" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -7401,6 +7450,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -7590,6 +7644,11 @@ "which": "^2.0.1" } }, + "d3-array": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-0.7.1.tgz", + "integrity": "sha1-oyHCFVhFnZlOtK1HtHgkDmSTOUI=" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8206,6 +8265,11 @@ "bser": "2.1.1" } }, + "fft.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fft.js/-/fft.js-4.0.4.tgz", + "integrity": "sha512-f9c00hphOgeQTlDyavwTtu6RiK8AIFjD6+jvXkNkpeQ7rirK3uFWVpalkoS4LAwbdX7mfZ8aoBfFVQX1Re/8aw==" + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -9598,6 +9662,11 @@ "tmpl": "1.0.5" } }, + "median-quickselect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/median-quickselect/-/median-quickselect-1.0.1.tgz", + "integrity": "sha1-3jQIA1pbLwQ4o5uZiT+vPn1hd/g=" + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -9686,6 +9755,26 @@ "ml-array-rescale": "^1.3.7" } }, + "ml-spectra-processing": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/ml-spectra-processing/-/ml-spectra-processing-11.6.0.tgz", + "integrity": "sha512-jUtNkcUIH+M091Ttf9JvtIYTxhgmjgudexHTSUP1y7yYrLkIEMUbqYYE9L5gLDoawrm8+BYa50Ke1JV47qGD0Q==", + "requires": { + "binary-search": "^1.3.6", + "cheminfo-types": "^1.1.0", + "fft.js": "^4.0.4", + "is-any-array": "^2.0.0", + "median-quickselect": "^1.0.1", + "ml-matrix": "^6.10.0", + "ml-xsadd": "^2.0.0", + "spline-interpolator": "^1.0.0" + } + }, + "ml-xsadd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-xsadd/-/ml-xsadd-2.0.0.tgz", + "integrity": "sha512-VoAYUqmPRmzKbbqRejjqceGFp3VF81Qe8XXFGU0UXLxB7Mf4GGvyGq5Qn3k4AiQgDEV6WzobqlPOd+j0+m6IrA==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -10212,6 +10301,14 @@ "dev": true, "peer": true }, + "spline-interpolator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spline-interpolator/-/spline-interpolator-1.0.0.tgz", + "integrity": "sha512-s8lowgsWE5wjHGEsk/4VADp7xAHw+pNy3OGp96fYjVTwLSx/83+BBmTFP2wZDRM0kj45q8zSyOV5fUcGn4hLEw==", + "requires": { + "d3-array": "^0.7.1" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index 9c5deca..9268d4b 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "dependencies": { "cheminfo-types": "^1.1.0", "install": "^0.13.0", - "ml-array-sequential-fill": "^1.1.8", - "ml-matrix": "^6.10.0" + "ml-matrix": "^6.10.0", + "ml-spectra-processing": "^11.6.0" }, "devDependencies": { "@types/jest": "^27.5.0", diff --git a/src/getShortestPath.ts b/src/getShortestPath.ts index c8a69a5..387de6f 100644 --- a/src/getShortestPath.ts +++ b/src/getShortestPath.ts @@ -1,5 +1,5 @@ import { DoubleArray } from 'cheminfo-types'; -import sequentialFill from 'ml-array-sequential-fill'; +import { xSequentialFill } from 'ml-spectra-processing'; import type { Matrix } from 'ml-matrix'; interface GetShortestPathOptions { @@ -28,7 +28,7 @@ export function getShortestPath(options: GetShortestPathOptions) { let scannedColumns = new Float64Array(nbColumns); let scannedRows = new Float64Array(nbRows); - let rows2Scan = sequentialFill({ from: 0, to: nbRows - 1, size: nbRows }); + let rows2Scan = Array.from(xSequentialFill({ from: 0, to: nbRows - 1 })); let numRows2Scan = nbRows; let sink = -1; From 20c8567ba0294da5c02293e3578f782e0c4d5864 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 23 May 2022 18:18:57 +0200 Subject: [PATCH 4/6] fix: close #16 --- src/__tests__/index.test.ts | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index 7bbfc99..6904151 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -1,6 +1,6 @@ import { toMatchCloseTo } from 'jest-matcher-deep-close-to'; -import linearSumAssignment from '..'; +import { linearSumAssignment } from '..'; expect.extend({ toMatchCloseTo }); diff --git a/src/index.ts b/src/index.ts index 2bccf90..bb79ab4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ interface Options { maximaze?: boolean; } -export default function linearSumAssignment( +export function linearSumAssignment( input: DoubleArray[] | Matrix, options: Options = {}, ) { From 1edbc3abbb8a64722860791a470046402a499fac Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 23 May 2022 18:31:28 +0200 Subject: [PATCH 5/6] fix: close #18 --- src/index.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/index.ts b/src/index.ts index bb79ab4..83136e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,10 +4,22 @@ import { Matrix } from 'ml-matrix'; import { getShortestPath } from './getShortestPath'; interface Options { + /** + * if true it will generate the assignment by the maximization of the cost. + * @default true + */ maximaze?: boolean; } +/** + * Implementation of Jonker-Volgenant shortest augmenting path algorithm based + * on the publication [On implementing 2D rectangular assignment algorithms](https://doi.org/10.1109/TAES.2016.140952) + */ + export function linearSumAssignment( + /** + * Cost matrix + */ input: DoubleArray[] | Matrix, options: Options = {}, ) { From 3e1ff4fd39215d84e372bd8f16eff72270aa25b9 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Thu, 26 May 2022 12:52:00 -0500 Subject: [PATCH 6/6] fix: update README closes: #18 #13 --- .gitignore | 160 ++++++++++++++++++++--------------------- README.md | 26 +++---- src/getShortestPath.ts | 2 +- src/index.ts | 2 +- 4 files changed, 93 insertions(+), 97 deletions(-) diff --git a/.gitignore b/.gitignore index 8857c98..91a5f1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,81 +1,81 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless - -# FuseBox cache -.fusebox/ - -lib -lib-esm - +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# FuseBox cache +.fusebox/ + +lib +lib-esm + .DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 72f5c67..5b664d0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ NMReDATA

- This package is the implementation of Jonker-Volgenant shortest augmenting path algorithm based on the publication [On implementing 2D rectangular assignment algorithms](https://doi.org/10.1109/TAES.2016.140952) @@ -17,11 +16,11 @@ If the number of rows is <= the number of columns, then every row is assigned to `$ npm i linear-sum-assignment` - ## Usage ```js import linearSumAssignment from 'linear-sum-assignment'; +import { xCostMatrix } from 'ml-spectra-processing'; /** * there is one more value in the experimental values, so one of @@ -35,12 +34,10 @@ const predicted = [3.1, 1.1, 1.9, 3.99, 5.2]; * rows and predicted in columns. * In this case we will look for the closest peak for each experimental peak value. **/ -const diff = experimental.map((experimental) => { - return predicted.map((predicted) => { - return Math.abs(predicted - experimental); - }); -}); +const diff = xCostMatrix(experimental, predicted, { + fct: (a, b) => Math.abs(a - b), +}); const result = linearSumAssignment(diff, { maximaze: false }); console.log(result); /** @@ -57,16 +54,15 @@ console.log(result); ], dualVariableForRows: Float64Array(6) [ 0, 0, 0, 0, 0, 0 ] } -*/ +*/ ``` - `rowAssignments` contains the index of the column assigned to each element in the rows (experimental). So the first element in experimental array is assigned to the second element of predicted. - `columnAssignments` contains the index of the row assigned to - each element in the columns. So the first element in - predicted is assigned to third element in - experimental. - `dualVariableForColumns` and `dualVariableForRows` are the Lagrange multipliers or dual variables. - `gain` the sum of the elements in the cost matrix. +`rowAssignments` contains the index of the column assigned to each element in the rows (experimental). + +`columnAssignments` contains the index of the row assigned to each element in the columns. So the first element in predicted is assigned to third element in experimental. +`dualVariableForColumns` and `dualVariableForRows` are the Lagrange multipliers or dual variables. +`gain` the sum of the elements in the cost matrix. + ## License [MIT](./LICENSE) diff --git a/src/getShortestPath.ts b/src/getShortestPath.ts index 387de6f..b70a505 100644 --- a/src/getShortestPath.ts +++ b/src/getShortestPath.ts @@ -1,6 +1,6 @@ import { DoubleArray } from 'cheminfo-types'; -import { xSequentialFill } from 'ml-spectra-processing'; import type { Matrix } from 'ml-matrix'; +import { xSequentialFill } from 'ml-spectra-processing'; interface GetShortestPathOptions { currUnAssCol: number; diff --git a/src/index.ts b/src/index.ts index 83136e7..b16945c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ interface Options { } /** - * Implementation of Jonker-Volgenant shortest augmenting path algorithm based + * Implementation of Jonker-Volgenant shortest augmenting path algorithm based * on the publication [On implementing 2D rectangular assignment algorithms](https://doi.org/10.1109/TAES.2016.140952) */