Skip to content

Commit

Permalink
feat(vectors): add new distance metrics
Browse files Browse the repository at this point in the history
- add distBrayCurtis()
- add distCanberra()
- add distHamming()
- add distJaccard()
- add distMinkowski()
- add distSorensenDice()
  • Loading branch information
postspectacular committed Aug 31, 2021
1 parent 1de245b commit 24aa2f4
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 0 deletions.
26 changes: 26 additions & 0 deletions packages/vectors/src/dist-braycurtis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { DistanceFn } from "./api";

/**
* Bray-Curtis **dissimilarity** metric. Result always in [0..1] interval.
*
* @remarks
* Reference: https://en.wikipedia.org/wiki/Bray%E2%80%93Curtis_dissimilarity
*
* @example
* ```ts
* distBrayCurtis([6, 7, 4], [10, 0, 6])
* // 0.393939...
* ```
*
* @param a
* @param b
*/
export const distBrayCurtis: DistanceFn = (a, b) => {
let c = 0;
let s = 0;
for (let i = a.length; i-- > 0; ) {
c += Math.abs(a[i] - b[i]);
s += Math.abs(a[i] + b[i]);
}
return s > 0 ? c / s : 0;
};
19 changes: 19 additions & 0 deletions packages/vectors/src/dist-canberra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { DistanceFn } from "./api";

/**
* @remarks
* Reference: https://en.wikipedia.org/wiki/Canberra_distance
*
* @param a
* @param b
*/
export const distCanberra: DistanceFn = (a, b) => {
let delta = 0;
for (let i = a.length; --i >= 0; ) {
const aa = a[i];
const bb = b[i];
const d = Math.abs(aa) + Math.abs(bb);
d > 0 && (delta += Math.abs(aa - bb) / d);
}
return delta;
};
4 changes: 4 additions & 0 deletions packages/vectors/src/dist-chebyshev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const $ = (dim: number) =>
)
);

/**
* @remarks
* Reference: https://en.wikipedia.org/wiki/Chebyshev_distance
*/
export const distChebyshev: MultiVecOpRoVV<number> = vop();

distChebyshev.default((a, b) => {
Expand Down
19 changes: 19 additions & 0 deletions packages/vectors/src/dist-hamming.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { DistanceFn } from "./api";

/**
* Normalized Hamming distance between `a` and `b`, i.e. number of differing
* components divided by vector size.
*
* @remarks
* Reference: https://en.wikipedia.org/wiki/Hamming_distance
*
* @param a
* @param b
*/
export const distHamming: DistanceFn = (a, b) => {
let delta = 0;
for (let i = a.length; --i >= 0; ) {
a[i] !== b[i] && delta++;
}
return delta / a.length;
};
20 changes: 20 additions & 0 deletions packages/vectors/src/dist-jaccard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { DistanceFn } from "./api";

/**
* @remarks
* Reference: https://en.wikipedia.org/wiki/Jaccard_index
*
* @param a
* @param b
*/
export const distJaccard: DistanceFn = (a, b) => {
let numNZ = 0;
let numEQ = 0;
for (let i = a.length; --i >= 0; ) {
const aa = a[i] !== 0;
const bb = b[i] !== 0;
numNZ += ~~(aa || bb);
numEQ += ~~(aa && bb);
}
return numNZ ? (numNZ - numEQ) / numNZ : 0;
};
4 changes: 4 additions & 0 deletions packages/vectors/src/dist-manhattan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const $ = (dim: number) =>
)
);

/**
* @remarks
* Reference: https://en.wikipedia.org/wiki/Taxicab_geometry
*/
export const distManhattan: MultiVecOpRoVV<number> = vop();

distManhattan.default(
Expand Down
19 changes: 19 additions & 0 deletions packages/vectors/src/dist-minkowski.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ReadonlyVec } from "./api";

/**
* @remarks
* The Minkowski power `p` MUST be > 0.
*
* Reference: https://en.wikipedia.org/wiki/Minkowski_distance
*
* @param a
* @param b
* @param p
*/
export const distMinkowski = (a: ReadonlyVec, b: ReadonlyVec, p: number) => {
let delta = 0;
for (let i = a.length; --i >= 0; ) {
delta += Math.abs(a[i] - b[i]) ** p;
}
return delta ** (1 / p);
};
20 changes: 20 additions & 0 deletions packages/vectors/src/dist-sorensendice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { DistanceFn } from "./api";

/**
* @remarks
* Reference: https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
*
* @param a
* @param b
*/
export const distSorensenDice: DistanceFn = (a, b) => {
let numTP = 0;
let numFP = 0;
for (let i = a.length; i-- > 0; ) {
const aa = a[i] !== 0;
const bb = b[i] !== 0;
numTP += ~~(aa && bb);
numFP += ~~(aa !== bb);
}
return numFP ? numFP / (2 * numTP + numFP) : 0;
};
6 changes: 6 additions & 0 deletions packages/vectors/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ export * from "./crosss";
export * from "./degrees";
export * from "./direction";
export * from "./dist";
export * from "./dist-braycurtis";
export * from "./dist-canberra";
export * from "./dist-chebyshev";
export * from "./dist-hamming";
export * from "./dist-haversine";
export * from "./dist-jaccard";
export * from "./dist-manhattan";
export * from "./dist-minkowski";
export * from "./dist-sorensendice";
export * from "./dist-weighted";
export * from "./distsq";
export * from "./div";
Expand Down

0 comments on commit 24aa2f4

Please sign in to comment.