@thi.ng/adjacency 2.1.11 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/bfs.js +4 -3
- package/binary.js +4 -4
- package/dfs.js +2 -2
- package/list.d.ts +6 -4
- package/list.js +49 -34
- package/package.json +11 -11
- package/sparse.js +4 -4
- package/utils.d.ts +3 -3
- package/utils.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2022-
|
|
3
|
+
- **Last updated**: 2022-08-01T14:53:59Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,19 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [2.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/adjacency@2.2.0) (2022-07-19)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- update AdjacencyList ([5d85d87](https://github.com/thi-ng/umbrella/commit/5d85d87))
|
|
17
|
+
- add vertices() iterator
|
|
18
|
+
- rename old `.vertices` field => `.adjacency`
|
|
19
|
+
- add adjListFromAdjacency() factory fn
|
|
20
|
+
|
|
21
|
+
#### ♻️ Refactoring
|
|
22
|
+
|
|
23
|
+
- update DCons call sites ([2dfec21](https://github.com/thi-ng/umbrella/commit/2dfec21))
|
|
24
|
+
|
|
12
25
|
## [2.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/adjacency@2.1.0) (2021-11-17)
|
|
13
26
|
|
|
14
27
|
#### 🚀 Features
|
package/bfs.js
CHANGED
|
@@ -10,7 +10,8 @@ export class BFS {
|
|
|
10
10
|
this.search(src, cost);
|
|
11
11
|
}
|
|
12
12
|
search(id, cost) {
|
|
13
|
-
const queue = new DCons()
|
|
13
|
+
const queue = new DCons();
|
|
14
|
+
queue.prepend(id);
|
|
14
15
|
const { dist, edges, graph, marked } = this;
|
|
15
16
|
dist.fill(0xffffffff);
|
|
16
17
|
dist[id] = 0;
|
|
@@ -37,9 +38,9 @@ export class BFS {
|
|
|
37
38
|
const { dist, edges } = this;
|
|
38
39
|
const path = new DCons();
|
|
39
40
|
for (; dist[id] > 0; id = edges[id]) {
|
|
40
|
-
path.
|
|
41
|
+
path.prepend(id);
|
|
41
42
|
}
|
|
42
|
-
path.
|
|
43
|
+
path.prepend(id);
|
|
43
44
|
return path;
|
|
44
45
|
}
|
|
45
46
|
}
|
package/binary.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BitMatrix } from "@thi.ng/bitfield/bitmatrix";
|
|
2
|
-
import {
|
|
2
|
+
import { __into, __invert, __toDot } from "./utils.js";
|
|
3
3
|
/**
|
|
4
4
|
* Adjacency matrix representation for both directed and undirected graphs and
|
|
5
5
|
* using a compact bit matrix to store edges. Each edge requires only 1 bit
|
|
@@ -11,7 +11,7 @@ export class AdjacencyBitMatrix {
|
|
|
11
11
|
this.mat = new BitMatrix(n);
|
|
12
12
|
this.undirected = undirected;
|
|
13
13
|
this.numE = 0;
|
|
14
|
-
edges &&
|
|
14
|
+
edges && __into(this, edges);
|
|
15
15
|
}
|
|
16
16
|
*edges() {
|
|
17
17
|
const directed = !this.undirected;
|
|
@@ -80,13 +80,13 @@ export class AdjacencyBitMatrix {
|
|
|
80
80
|
return res;
|
|
81
81
|
}
|
|
82
82
|
invert() {
|
|
83
|
-
return
|
|
83
|
+
return __invert(new AdjacencyBitMatrix(this.mat.n, undefined, this.undirected), this.edges());
|
|
84
84
|
}
|
|
85
85
|
toString() {
|
|
86
86
|
return this.mat.toString();
|
|
87
87
|
}
|
|
88
88
|
toDot(ids) {
|
|
89
|
-
return
|
|
89
|
+
return __toDot(this.edges(), this.undirected, ids);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
/**
|
package/dfs.js
CHANGED
package/list.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Nullable } from "@thi.ng/api";
|
|
2
2
|
import type { DegreeType, Edge, IGraph } from "./api.js";
|
|
3
3
|
export declare class AdjacencyList implements IGraph<number> {
|
|
4
|
-
|
|
4
|
+
adjacency: number[][];
|
|
5
5
|
indegree: number[];
|
|
6
6
|
protected numE: number;
|
|
7
7
|
protected numV: number;
|
|
8
8
|
constructor(edges?: Iterable<Edge>);
|
|
9
9
|
numEdges(): number;
|
|
10
10
|
numVertices(): number;
|
|
11
|
+
vertices(): Generator<number, void, unknown>;
|
|
11
12
|
edges(): Generator<Edge<number>, void, unknown>;
|
|
12
13
|
addVertex(id: number): void;
|
|
13
14
|
removeVertex(id: number): boolean;
|
|
@@ -17,9 +18,10 @@ export declare class AdjacencyList implements IGraph<number> {
|
|
|
17
18
|
degree(id: number, type?: DegreeType): number;
|
|
18
19
|
neighbors(id: number): Iterable<number>;
|
|
19
20
|
invert(): AdjacencyList;
|
|
20
|
-
toString(): string;
|
|
21
21
|
toDot(ids?: string[]): string;
|
|
22
|
-
|
|
22
|
+
toString(): string;
|
|
23
|
+
protected ensureVertexData(id: number): number[];
|
|
23
24
|
}
|
|
24
25
|
export declare const defAdjList: (edges?: Iterable<Edge>) => AdjacencyList;
|
|
26
|
+
export declare const adjListFromAdjacency: (src: Nullable<number[]>[]) => AdjacencyList;
|
|
25
27
|
//# sourceMappingURL=list.d.ts.map
|
package/list.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { into, invert, toDot } from "./utils.js";
|
|
1
|
+
import { __into, __invert, __toDot } from "./utils.js";
|
|
3
2
|
export class AdjacencyList {
|
|
4
3
|
constructor(edges) {
|
|
5
|
-
this.
|
|
4
|
+
this.adjacency = [];
|
|
6
5
|
this.indegree = [];
|
|
7
6
|
this.numE = 0;
|
|
8
7
|
this.numV = 0;
|
|
9
|
-
edges &&
|
|
8
|
+
edges && __into(this, edges);
|
|
10
9
|
}
|
|
11
10
|
numEdges() {
|
|
12
11
|
return this.numE;
|
|
@@ -14,10 +13,17 @@ export class AdjacencyList {
|
|
|
14
13
|
numVertices() {
|
|
15
14
|
return this.numV;
|
|
16
15
|
}
|
|
16
|
+
*vertices() {
|
|
17
|
+
const { adjacency } = this;
|
|
18
|
+
for (let i = 0, n = adjacency.length; i < n; i++) {
|
|
19
|
+
if (adjacency[i])
|
|
20
|
+
yield i;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
17
23
|
*edges() {
|
|
18
|
-
const
|
|
19
|
-
for (let i = 0, n =
|
|
20
|
-
const vertex =
|
|
24
|
+
const { adjacency } = this;
|
|
25
|
+
for (let i = 0, n = adjacency.length; i < n; i++) {
|
|
26
|
+
const vertex = adjacency[i];
|
|
21
27
|
if (!vertex)
|
|
22
28
|
continue;
|
|
23
29
|
for (let j of vertex)
|
|
@@ -28,24 +34,22 @@ export class AdjacencyList {
|
|
|
28
34
|
this.ensureVertexData(id);
|
|
29
35
|
}
|
|
30
36
|
removeVertex(id) {
|
|
31
|
-
const {
|
|
32
|
-
const vertex =
|
|
37
|
+
const { adjacency, indegree } = this;
|
|
38
|
+
const vertex = adjacency[id];
|
|
33
39
|
if (!vertex)
|
|
34
40
|
return false;
|
|
35
41
|
// remove outgoing
|
|
36
42
|
while (vertex.length) {
|
|
37
|
-
|
|
38
|
-
vertex.drop();
|
|
39
|
-
indegree[to]--;
|
|
43
|
+
indegree[vertex.pop()]--;
|
|
40
44
|
this.numE--;
|
|
41
45
|
}
|
|
42
|
-
delete
|
|
46
|
+
delete adjacency[id];
|
|
43
47
|
// remove incoming
|
|
44
|
-
for (let i = 0, n =
|
|
45
|
-
const vertex =
|
|
48
|
+
for (let i = 0, n = adjacency.length; i < n && indegree[id] > 0; i++) {
|
|
49
|
+
const vertex = adjacency[i];
|
|
46
50
|
if (!vertex)
|
|
47
51
|
continue;
|
|
48
|
-
while (
|
|
52
|
+
while (vertex.includes(id))
|
|
49
53
|
this.removeEdge(i, id);
|
|
50
54
|
}
|
|
51
55
|
this.numV--;
|
|
@@ -60,11 +64,11 @@ export class AdjacencyList {
|
|
|
60
64
|
return true;
|
|
61
65
|
}
|
|
62
66
|
removeEdge(from, to) {
|
|
63
|
-
const vertex = this.
|
|
67
|
+
const vertex = this.adjacency[from];
|
|
64
68
|
if (vertex) {
|
|
65
|
-
const dest = vertex.
|
|
66
|
-
if (dest) {
|
|
67
|
-
vertex.
|
|
69
|
+
const dest = vertex.indexOf(to);
|
|
70
|
+
if (dest >= 0) {
|
|
71
|
+
vertex.splice(dest, 1);
|
|
68
72
|
this.numE--;
|
|
69
73
|
this.indegree[to]--;
|
|
70
74
|
return true;
|
|
@@ -73,12 +77,12 @@ export class AdjacencyList {
|
|
|
73
77
|
return false;
|
|
74
78
|
}
|
|
75
79
|
hasEdge(from, to) {
|
|
76
|
-
const vertex = this.
|
|
77
|
-
return vertex ?
|
|
80
|
+
const vertex = this.adjacency[from];
|
|
81
|
+
return vertex ? vertex.includes(to) : false;
|
|
78
82
|
}
|
|
79
83
|
degree(id, type = "out") {
|
|
80
84
|
let degree = 0;
|
|
81
|
-
const vertex = this.
|
|
85
|
+
const vertex = this.adjacency[id];
|
|
82
86
|
if (vertex) {
|
|
83
87
|
if (type !== "in")
|
|
84
88
|
degree += vertex.length;
|
|
@@ -88,33 +92,44 @@ export class AdjacencyList {
|
|
|
88
92
|
return degree;
|
|
89
93
|
}
|
|
90
94
|
neighbors(id) {
|
|
91
|
-
return [...(this.
|
|
95
|
+
return [...(this.adjacency[id] || [])];
|
|
92
96
|
}
|
|
93
97
|
invert() {
|
|
94
|
-
return
|
|
98
|
+
return __invert(new AdjacencyList(), this.edges());
|
|
99
|
+
}
|
|
100
|
+
toDot(ids) {
|
|
101
|
+
return __toDot(this.edges(), false, ids);
|
|
95
102
|
}
|
|
96
103
|
toString() {
|
|
97
|
-
const
|
|
104
|
+
const { adjacency } = this;
|
|
98
105
|
const res = [];
|
|
99
|
-
for (let i = 0, n =
|
|
100
|
-
if (
|
|
101
|
-
res.push(`${i}: [${[...
|
|
106
|
+
for (let i = 0, n = adjacency.length; i < n; i++) {
|
|
107
|
+
if (adjacency[i]) {
|
|
108
|
+
res.push(`${i}: [${[...adjacency[i]]
|
|
102
109
|
.sort((a, b) => a - b)
|
|
103
110
|
.join(", ")}]`);
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
113
|
return res.join("\n");
|
|
107
114
|
}
|
|
108
|
-
toDot(ids) {
|
|
109
|
-
return toDot(this.edges(), false, ids);
|
|
110
|
-
}
|
|
111
115
|
ensureVertexData(id) {
|
|
112
|
-
const vertex = this.
|
|
116
|
+
const vertex = this.adjacency[id];
|
|
113
117
|
if (vertex)
|
|
114
118
|
return vertex;
|
|
115
119
|
this.numV++;
|
|
116
120
|
this.indegree[id] = 0;
|
|
117
|
-
return (this.
|
|
121
|
+
return (this.adjacency[id] = []);
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
export const defAdjList = (edges) => new AdjacencyList(edges);
|
|
125
|
+
export const adjListFromAdjacency = (src) => {
|
|
126
|
+
const res = new AdjacencyList();
|
|
127
|
+
for (let i = 0, n = src.length; i < n; i++) {
|
|
128
|
+
const v = src[i];
|
|
129
|
+
if (!v)
|
|
130
|
+
continue;
|
|
131
|
+
for (let w of v)
|
|
132
|
+
res.addEdge(i, w);
|
|
133
|
+
}
|
|
134
|
+
return res;
|
|
135
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/adjacency",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Sparse & bitwise adjacency matrices and related functions for directed & undirected graphs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -34,21 +34,21 @@
|
|
|
34
34
|
"test": "testament test"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@thi.ng/api": "^8.3.
|
|
38
|
-
"@thi.ng/arrays": "^2.2
|
|
39
|
-
"@thi.ng/bitfield": "^2.1
|
|
40
|
-
"@thi.ng/dcons": "^3.2.
|
|
41
|
-
"@thi.ng/errors": "^2.1.
|
|
42
|
-
"@thi.ng/sparse": "^0.3.
|
|
37
|
+
"@thi.ng/api": "^8.3.9",
|
|
38
|
+
"@thi.ng/arrays": "^2.3.2",
|
|
39
|
+
"@thi.ng/bitfield": "^2.2.1",
|
|
40
|
+
"@thi.ng/dcons": "^3.2.8",
|
|
41
|
+
"@thi.ng/errors": "^2.1.9",
|
|
42
|
+
"@thi.ng/sparse": "^0.3.13"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@microsoft/api-extractor": "^7.25.0",
|
|
46
|
-
"@thi.ng/testament": "^0.2.
|
|
47
|
-
"@thi.ng/vectors": "^7.5.
|
|
46
|
+
"@thi.ng/testament": "^0.2.10",
|
|
47
|
+
"@thi.ng/vectors": "^7.5.9",
|
|
48
48
|
"rimraf": "^3.0.2",
|
|
49
49
|
"tools": "^0.0.1",
|
|
50
50
|
"typedoc": "^0.22.17",
|
|
51
|
-
"typescript": "^4.7.
|
|
51
|
+
"typescript": "^4.7.4"
|
|
52
52
|
},
|
|
53
53
|
"keywords": [
|
|
54
54
|
"adjacency",
|
|
@@ -119,5 +119,5 @@
|
|
|
119
119
|
],
|
|
120
120
|
"year": 2018
|
|
121
121
|
},
|
|
122
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "976ccd698cedaa60dcef2e69030a5eb98898cc4a\n"
|
|
123
123
|
}
|
package/sparse.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ensureIndex2 } from "@thi.ng/errors/out-of-bounds";
|
|
2
2
|
import { CSR } from "@thi.ng/sparse/csr";
|
|
3
|
-
import {
|
|
3
|
+
import { __into, __invert, __toDot } from "./utils.js";
|
|
4
4
|
export class AdjacencyMatrix extends CSR {
|
|
5
5
|
constructor(n, data, rows, cols, undirected = false) {
|
|
6
6
|
super(n, n, data, rows, cols);
|
|
@@ -58,7 +58,7 @@ export class AdjacencyMatrix extends CSR {
|
|
|
58
58
|
return this.nzRowCols(id);
|
|
59
59
|
}
|
|
60
60
|
invert() {
|
|
61
|
-
return
|
|
61
|
+
return __invert(defAdjMatrix(this.m, undefined, this.undirected), this.edges());
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Returns a diagonal sparse matrix {@link @thi.ng/sparse#CSR} containing
|
|
@@ -140,7 +140,7 @@ export class AdjacencyMatrix extends CSR {
|
|
|
140
140
|
.add(deg.sub(I).mulN(n * n));
|
|
141
141
|
}
|
|
142
142
|
toDot(ids) {
|
|
143
|
-
return
|
|
143
|
+
return __toDot(this.edges(), this.undirected, ids);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
@@ -156,6 +156,6 @@ export class AdjacencyMatrix extends CSR {
|
|
|
156
156
|
export const defAdjMatrix = (n, edges, undirected = false) => {
|
|
157
157
|
const raw = CSR.empty(n);
|
|
158
158
|
const mat = new AdjacencyMatrix(n, raw.data, raw.rows, raw.cols, undirected);
|
|
159
|
-
edges &&
|
|
159
|
+
edges && __into(mat, edges);
|
|
160
160
|
return mat;
|
|
161
161
|
};
|
package/utils.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Pair } from "@thi.ng/api";
|
|
2
2
|
import type { Edge, IGraph } from "./api.js";
|
|
3
3
|
/** @internal */
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const __toDot: (edges: Iterable<Pair<number, number>>, undirected: boolean, ids?: string[]) => string;
|
|
5
5
|
/** @internal */
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const __into: (graph: IGraph, edges: Iterable<Edge>) => void;
|
|
7
7
|
/** @internal */
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const __invert: <T extends IGraph<number>>(graph: T, edges: Iterable<Edge>) => T;
|
|
9
9
|
//# sourceMappingURL=utils.d.ts.map
|
package/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export const
|
|
2
|
+
export const __toDot = (edges, undirected, ids) => {
|
|
3
3
|
const [type, sep] = undirected ? ["graph", "--"] : ["digraph", "->"];
|
|
4
4
|
const res = [`${type} g {`];
|
|
5
5
|
for (let e of edges) {
|
|
@@ -11,13 +11,13 @@ export const toDot = (edges, undirected, ids) => {
|
|
|
11
11
|
return res.join("\n");
|
|
12
12
|
};
|
|
13
13
|
/** @internal */
|
|
14
|
-
export const
|
|
14
|
+
export const __into = (graph, edges) => {
|
|
15
15
|
for (let e of edges) {
|
|
16
16
|
graph.addEdge(e[0], e[1]);
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
/** @internal */
|
|
20
|
-
export const
|
|
20
|
+
export const __invert = (graph, edges) => {
|
|
21
21
|
for (let e of edges) {
|
|
22
22
|
graph.addEdge(e[1], e[0]);
|
|
23
23
|
}
|