From dae97ffb2d5d085b3f60995bd097d88c3b7efee4 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 17 Feb 2019 17:21:45 +0000 Subject: [PATCH] feat(adjacency): add bitmatrix edge counting, add/fix toDot() impls, add tests --- packages/adjacency/src/binary.ts | 24 ++++++++++++++++----- packages/adjacency/src/index.ts | 2 +- packages/adjacency/src/sparse.ts | 6 ++---- packages/adjacency/test/binary.ts | 35 +++++++++++++++++++++++++++++++ packages/adjacency/test/index.ts | 6 ------ packages/adjacency/test/sparse.ts | 32 ++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 packages/adjacency/test/binary.ts delete mode 100644 packages/adjacency/test/index.ts create mode 100644 packages/adjacency/test/sparse.ts diff --git a/packages/adjacency/src/binary.ts b/packages/adjacency/src/binary.ts index 925624fd3c..297b5ee402 100644 --- a/packages/adjacency/src/binary.ts +++ b/packages/adjacency/src/binary.ts @@ -25,11 +25,13 @@ export class AdjacencyBitMatrix implements } mat: BitMatrix; - undirected: boolean; + protected undirected: boolean; + protected numE: number; constructor(n: number, undirected = false) { this.mat = new BitMatrix(n); this.undirected = undirected; + this.numE = 0; } *edges() { @@ -44,11 +46,11 @@ export class AdjacencyBitMatrix implements } numEdges(): number { - throw new Error("Method not implemented."); + return this.numE; } numVertices(): number { - throw new Error("Method not implemented."); + return this.mat.n; } /** @@ -62,13 +64,13 @@ export class AdjacencyBitMatrix implements } addEdge(from: number, to: number) { - this.mat.setAt(to, from, true); + !this.mat.setAt(to, from, true) && this.numE++; this.undirected && this.mat.setAt(from, to, true); return this; } removeEdge(from: number, to: number) { - this.mat.setAt(to, from, false); + this.mat.setAt(to, from, false) && this.numE--; this.undirected && this.mat.setAt(from, to, false); return this; } @@ -107,4 +109,16 @@ export class AdjacencyBitMatrix implements toString() { return this.mat.toString(); } + + toDot() { + const [type, sep] = this.undirected ? + ["graph", "--"] : + ["digraph", "->"]; + const res = [`${type} g {`]; + for (let e of this.edges()) { + res.push(`"${e[0]}"${sep}"${e[1]}";`); + } + res.push(`}`); + return res.join("\n"); + } } diff --git a/packages/adjacency/src/index.ts b/packages/adjacency/src/index.ts index 74bd87346b..d2c2c80ec7 100644 --- a/packages/adjacency/src/index.ts +++ b/packages/adjacency/src/index.ts @@ -1,3 +1,3 @@ export * from "./api"; -export * from "./adjacency"; export * from "./binary"; +export * from "./sparse"; diff --git a/packages/adjacency/src/sparse.ts b/packages/adjacency/src/sparse.ts index 545ff013e2..ec436e0105 100644 --- a/packages/adjacency/src/sparse.ts +++ b/packages/adjacency/src/sparse.ts @@ -157,10 +157,8 @@ export class AdjacencyMatrix extends CSR implements ["graph", "--"] : ["digraph", "->"]; const res = [`${type} g {`]; - for (let i = 0; i < this.m; i++) { - for (let j of this.nzRowCols(i)) { - res.push(`"${j}"${sep}"${i}";`); - } + for (let e of this.edges()) { + res.push(`"${e[0]}"${sep}"${e[1]}";`); } res.push(`}`); return res.join("\n"); diff --git a/packages/adjacency/test/binary.ts b/packages/adjacency/test/binary.ts new file mode 100644 index 0000000000..4073e650b5 --- /dev/null +++ b/packages/adjacency/test/binary.ts @@ -0,0 +1,35 @@ +import { Pair } from "@thi.ng/api"; +import { AdjacencyBitMatrix } from "../src/index"; +import * as assert from "assert"; + +const edges: Pair[] = [ + [2, 3], + [0, 1], + [5, 4], + [2, 0], +]; + +describe("adjacency (bitmatrix)", () => { + it("fromEdges, undirected", () => { + const m = AdjacencyBitMatrix.fromEdges(6, edges, true); + console.log([...m.edges()]); + assert.deepEqual( + m.mat.data.slice(0, 6), + [ + 1610612736, + 2147483648, + 2415919104, + 536870912, + 67108864, + 134217728 + ], + "data" + ); + assert.equal(m.numEdges(), 4, "numEdges"); + assert.deepEqual( + [...m.edges()], + [[4, 5], [2, 3], [0, 1], [0, 2]], + "edges" + ); + }); +}); diff --git a/packages/adjacency/test/index.ts b/packages/adjacency/test/index.ts deleted file mode 100644 index 9135e42175..0000000000 --- a/packages/adjacency/test/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// import * as assert from "assert"; -// import * as a from "../src/index"; - -describe("adjacency", () => { - it("tests pending"); -}); diff --git a/packages/adjacency/test/sparse.ts b/packages/adjacency/test/sparse.ts new file mode 100644 index 0000000000..cfa3ee7a9c --- /dev/null +++ b/packages/adjacency/test/sparse.ts @@ -0,0 +1,32 @@ +import { Pair } from "@thi.ng/api"; +import { AdjacencyMatrix } from "../src/index"; +import * as assert from "assert"; + +const edges: Pair[] = [ + [2, 3], + [0, 1], + [5, 4], + [2, 0], +]; + +describe("adjacency (sparse)", () => { + it("fromEdges, undirected", () => { + const m = AdjacencyMatrix.fromEdges(6, edges, true); + assert.deepEqual( + m.rows, + [0, 2, 3, 5, 6, 7, 8], + "rows" + ); + assert.deepEqual( + m.cols, + [1, 2, 0, 0, 3, 2, 5, 4], + "cols" + ); + assert.equal(m.numEdges(), 4, "numEdges"); + assert.deepEqual( + [...m.edges()], + [[0, 1], [0, 2], [2, 3], [4, 5]], + "edges" + ); + }); +});