@thi.ng/adjacency
Version:
Sparse & bitwise adjacency matrices, lists and selected traversal algorithms for directed & undirected graphs
100 lines (99 loc) • 2.41 kB
JavaScript
import { BitMatrix } from "@thi.ng/bitfield/bitmatrix";
import { __into, __invert, __toDot } from "./utils.js";
class AdjacencyBitMatrix {
mat;
undirected;
numE;
constructor(n, edges, undirected = false) {
this.mat = new BitMatrix(n);
this.undirected = undirected;
this.numE = 0;
edges && __into(this, edges);
}
*edges() {
const directed = !this.undirected;
for (let i = this.mat.m; i-- > 0; ) {
for (let n of this.neighbors(i)) {
if (directed || n > i) {
yield [i, n];
}
}
}
}
numEdges() {
return this.numE;
}
numVertices() {
return this.mat.m;
}
/**
* Resizes matrix to new size given.
*
* @param n - new max vertices
*/
resize(n) {
this.mat.resize(n);
return this;
}
addEdge(from, to) {
if (!this.mat.setAt(from, to, true)) {
this.numE++;
this.undirected && this.mat.setAt(to, from, true);
return true;
}
return false;
}
removeEdge(from, to) {
if (this.mat.setAt(from, to, false)) {
this.numE--;
this.undirected && this.mat.setAt(to, from, false);
return true;
}
return false;
}
hasEdge(from, to) {
return this.mat.at(from, to) !== 0;
}
hasVertex(id) {
return this.mat.popCountRow(id) !== 0 || this.mat.popCountColumn(id) !== 0;
}
degree(id, type = "out") {
let degree = 0;
if (this.undirected || type !== "in")
degree += this.mat.popCountRow(id);
if (!this.undirected && type !== "out")
degree += this.mat.popCountColumn(id);
return degree;
}
neighbors(id) {
return [...this.mat.row(id, true).positions()];
}
similarity(id, threshold = 0) {
const mat = this.mat;
const query = mat.row(id, true);
const acc = [];
for (let i = 0, m = mat.m; i < m; i++) {
if (i === id) continue;
const sim = query.similarity(mat.row(i, true));
if (sim >= threshold) acc.push([i, sim]);
}
return acc.sort((a, b) => b[1] - a[1]);
}
invert() {
return __invert(
new AdjacencyBitMatrix(this.mat.n, void 0, this.undirected),
this.edges()
);
}
toString() {
return this.mat.toString();
}
toDot(ids) {
return __toDot(this.edges(), this.undirected, ids);
}
}
const defAdjBitMatrix = (n, edges, undirected) => new AdjacencyBitMatrix(n, edges, undirected);
export {
AdjacencyBitMatrix,
defAdjBitMatrix
};