@thi.ng/adjacency 2.5.12 → 2.5.14

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/sparse.js CHANGED
@@ -1,168 +1,171 @@
1
1
  import { ensureIndex2 } from "@thi.ng/errors/out-of-bounds";
2
2
  import { CSR } from "@thi.ng/sparse/csr";
3
3
  import { __into, __invert, __toDot } from "./utils.js";
4
- export class AdjacencyMatrix extends CSR {
5
- undirected;
6
- constructor(n, data, rows, cols, undirected = false) {
7
- super(n, n, data, rows, cols);
8
- this.undirected = undirected;
9
- }
10
- *edges() {
11
- const { cols, rows } = this;
12
- const directed = !this.undirected;
13
- for (let i = 0; i < this.m; i++) {
14
- const jj = rows[i + 1];
15
- for (let j = rows[i]; j < jj; j++) {
16
- const k = cols[j];
17
- if (directed || i <= k) {
18
- yield [i, k];
19
- }
20
- }
4
+ class AdjacencyMatrix extends CSR {
5
+ undirected;
6
+ constructor(n, data, rows, cols, undirected = false) {
7
+ super(n, n, data, rows, cols);
8
+ this.undirected = undirected;
9
+ }
10
+ *edges() {
11
+ const { cols, rows } = this;
12
+ const directed = !this.undirected;
13
+ for (let i = 0; i < this.m; i++) {
14
+ const jj = rows[i + 1];
15
+ for (let j = rows[i]; j < jj; j++) {
16
+ const k = cols[j];
17
+ if (directed || i <= k) {
18
+ yield [i, k];
21
19
  }
22
- }
23
- addEdge(from, to) {
24
- if (!this.at(from, to)) {
25
- this.setAt(from, to, 1, false);
26
- this.undirected && this.setAt(to, from, 1, false);
27
- return true;
20
+ }
21
+ }
22
+ }
23
+ addEdge(from, to) {
24
+ if (!this.at(from, to)) {
25
+ this.setAt(from, to, 1, false);
26
+ this.undirected && this.setAt(to, from, 1, false);
27
+ return true;
28
+ }
29
+ return false;
30
+ }
31
+ removeEdge(from, to) {
32
+ if (this.at(from, to)) {
33
+ this.setAt(from, to, 0, false);
34
+ this.undirected && this.setAt(to, from, 0, false);
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ hasEdge(from, to) {
40
+ return this.at(from, to) !== 0;
41
+ }
42
+ hasVertex(id) {
43
+ return this.degree(id, "inout") > 0;
44
+ }
45
+ numEdges() {
46
+ const n = this.data.length;
47
+ return this.undirected ? n / 2 : n;
48
+ }
49
+ numVertices() {
50
+ return this.m;
51
+ }
52
+ degree(id, type = "out") {
53
+ let degree = 0;
54
+ ensureIndex2(id, id, this.m, this.n);
55
+ if (this.undirected || type !== "in")
56
+ degree += this.nnzRow(id);
57
+ if (!this.undirected && type !== "out")
58
+ degree += this.nnzCol(id);
59
+ return degree;
60
+ }
61
+ neighbors(id) {
62
+ return this.nzRowCols(id);
63
+ }
64
+ invert() {
65
+ return __invert(
66
+ defAdjMatrix(this.m, void 0, this.undirected),
67
+ this.edges()
68
+ );
69
+ }
70
+ /**
71
+ * Returns a diagonal sparse matrix
72
+ * [`CSR`](https://docs.thi.ng/umbrella/sparse/classes/CSR.html) containing
73
+ * information about the degree of each vertex, i.e. the number of edges
74
+ * attached to each vertex.
75
+ *
76
+ * @remarks
77
+ * Reference: https://en.wikipedia.org/wiki/Degree_matrix
78
+ *
79
+ * @param deg - degree type
80
+ */
81
+ degreeMat(deg = "out") {
82
+ const res = CSR.empty(this.m);
83
+ switch (deg) {
84
+ case "out":
85
+ default:
86
+ for (let i = this.m; i-- > 0; ) {
87
+ res.setAt(i, i, this.nnzRow(i));
28
88
  }
29
- return false;
30
- }
31
- removeEdge(from, to) {
32
- if (this.at(from, to)) {
33
- this.setAt(from, to, 0, false);
34
- this.undirected && this.setAt(to, from, 0, false);
35
- return true;
89
+ break;
90
+ case "in":
91
+ for (let i = this.m; i-- > 0; ) {
92
+ res.setAt(i, i, this.nnzCol(i));
36
93
  }
37
- return false;
38
- }
39
- hasEdge(from, to) {
40
- return this.at(from, to) !== 0;
41
- }
42
- hasVertex(id) {
43
- return this.degree(id, "inout") > 0;
44
- }
45
- numEdges() {
46
- const n = this.data.length;
47
- return this.undirected ? n / 2 : n;
48
- }
49
- numVertices() {
50
- return this.m;
51
- }
52
- degree(id, type = "out") {
53
- let degree = 0;
54
- ensureIndex2(id, id, this.m, this.n);
55
- if (this.undirected || type !== "in")
56
- degree += this.nnzRow(id);
57
- if (!this.undirected && type !== "out")
58
- degree += this.nnzCol(id);
59
- return degree;
60
- }
61
- neighbors(id) {
62
- return this.nzRowCols(id);
63
- }
64
- invert() {
65
- return __invert(defAdjMatrix(this.m, undefined, this.undirected), this.edges());
66
- }
67
- /**
68
- * Returns a diagonal sparse matrix
69
- * [`CSR`](https://docs.thi.ng/umbrella/sparse/classes/CSR.html) containing
70
- * information about the degree of each vertex, i.e. the number of edges
71
- * attached to each vertex.
72
- *
73
- * @remarks
74
- * Reference: https://en.wikipedia.org/wiki/Degree_matrix
75
- *
76
- * @param deg - degree type
77
- */
78
- degreeMat(deg = "out") {
79
- const res = CSR.empty(this.m);
80
- switch (deg) {
81
- case "out":
82
- default:
83
- for (let i = this.m; i-- > 0;) {
84
- res.setAt(i, i, this.nnzRow(i));
85
- }
86
- break;
87
- case "in":
88
- for (let i = this.m; i-- > 0;) {
89
- res.setAt(i, i, this.nnzCol(i));
90
- }
91
- break;
92
- case "inout":
93
- for (let i = this.m; i-- > 0;) {
94
- res.setAt(i, i, this.nnzRow(i) + this.nnzCol(i));
95
- }
96
- break;
94
+ break;
95
+ case "inout":
96
+ for (let i = this.m; i-- > 0; ) {
97
+ res.setAt(i, i, this.nnzRow(i) + this.nnzCol(i));
97
98
  }
98
- return res;
99
- }
100
- /**
101
- * Returns this graph's Laplacian matrix: `L = D - A` Where `D` is the
102
- * degree matrix and `A` this adjacency matrix.
103
- *
104
- * @remarks
105
- * References:
106
- * - https://en.wikipedia.org/wiki/Laplacian_matrix
107
- * - https://en.wikipedia.org/wiki/Discrete_Laplace_operator
108
- *
109
- * @param deg - degree type for {@link AdjacencyMatrix.degreeMat}
110
- */
111
- laplacianMat(deg) {
112
- return (deg || this.degreeMat()).sub(this);
113
- }
114
- normalizedLaplacian(deg) {
115
- deg = deg || this.degreeMat();
116
- const m = this.m;
117
- const res = CSR.empty(m);
118
- for (let i = 0; i < m; i++) {
119
- for (let j = 0; j < m; j++) {
120
- if (i === j && deg.at(i, i) > 0) {
121
- res.setAt(i, j, 1);
122
- }
123
- else if (i !== j && this.at(i, j) > 0) {
124
- res.setAt(i, j, -1 / Math.sqrt(deg.at(i, i) * deg.at(j, j)));
125
- }
126
- }
99
+ break;
100
+ }
101
+ return res;
102
+ }
103
+ /**
104
+ * Returns this graph's Laplacian matrix: `L = D - A` Where `D` is the
105
+ * degree matrix and `A` this adjacency matrix.
106
+ *
107
+ * @remarks
108
+ * References:
109
+ * - https://en.wikipedia.org/wiki/Laplacian_matrix
110
+ * - https://en.wikipedia.org/wiki/Discrete_Laplace_operator
111
+ *
112
+ * @param deg - degree type for {@link AdjacencyMatrix.degreeMat}
113
+ */
114
+ laplacianMat(deg) {
115
+ return (deg || this.degreeMat()).sub(this);
116
+ }
117
+ normalizedLaplacian(deg) {
118
+ deg = deg || this.degreeMat();
119
+ const m = this.m;
120
+ const res = CSR.empty(m);
121
+ for (let i = 0; i < m; i++) {
122
+ for (let j = 0; j < m; j++) {
123
+ if (i === j && deg.at(i, i) > 0) {
124
+ res.setAt(i, j, 1);
125
+ } else if (i !== j && this.at(i, j) > 0) {
126
+ res.setAt(
127
+ i,
128
+ j,
129
+ -1 / Math.sqrt(deg.at(i, i) * deg.at(j, j))
130
+ );
127
131
  }
128
- return res;
129
- }
130
- /**
131
- * Computes: `I - nA + n^2 * (D - I)`, where `I` is the identity matrix,
132
- * `A` the adjacency matrix, `D` the degree matrix, and `n` is a
133
- * (complex-valued) number.
134
- *
135
- * @remarks
136
- * See {@link AdjacencyMatrix.degreeMat}.
137
- *
138
- * @param n - scale factor
139
- * @param deg - degree matrix
140
- */
141
- deformedLaplacian(n, deg) {
142
- deg = deg ? deg.copy() : this.degreeMat();
143
- const I = CSR.identity(this.m);
144
- return I.copy()
145
- .sub(this.copy().mulN(n))
146
- .add(deg.sub(I).mulN(n * n));
147
- }
148
- toDot(ids) {
149
- return __toDot(this.edges(), this.undirected, ids);
150
- }
132
+ }
133
+ }
134
+ return res;
135
+ }
136
+ /**
137
+ * Computes: `I - nA + n^2 * (D - I)`, where `I` is the identity matrix,
138
+ * `A` the adjacency matrix, `D` the degree matrix, and `n` is a
139
+ * (complex-valued) number.
140
+ *
141
+ * @remarks
142
+ * See {@link AdjacencyMatrix.degreeMat}.
143
+ *
144
+ * @param n - scale factor
145
+ * @param deg - degree matrix
146
+ */
147
+ deformedLaplacian(n, deg) {
148
+ deg = deg ? deg.copy() : this.degreeMat();
149
+ const I = CSR.identity(this.m);
150
+ return I.copy().sub(this.copy().mulN(n)).add(deg.sub(I).mulN(n * n));
151
+ }
152
+ toDot(ids) {
153
+ return __toDot(this.edges(), this.undirected, ids);
154
+ }
151
155
  }
152
- /**
153
- * Creates an adjacency matrix backed by a sparse
154
- * [`CSR`](https://docs.thi.ng/umbrella/sparse/classes/CSR.html) matrix,
155
- * optionally initialize with given edge pairs. Each edge is a `[src, dest]`
156
- * tuple. If `undirected` is true (default: false), creates symmetrical edges
157
- * (i.e. undirected graph).
158
- *
159
- * @param n - max number of vertices
160
- * @param edges - edge pairs
161
- * @param undirected - true, if undirected
162
- */
163
- export const defAdjMatrix = (n, edges, undirected = false) => {
164
- const raw = CSR.empty(n);
165
- const mat = new AdjacencyMatrix(n, raw.data, raw.rows, raw.cols, undirected);
166
- edges && __into(mat, edges);
167
- return mat;
156
+ const defAdjMatrix = (n, edges, undirected = false) => {
157
+ const raw = CSR.empty(n);
158
+ const mat = new AdjacencyMatrix(
159
+ n,
160
+ raw.data,
161
+ raw.rows,
162
+ raw.cols,
163
+ undirected
164
+ );
165
+ edges && __into(mat, edges);
166
+ return mat;
167
+ };
168
+ export {
169
+ AdjacencyMatrix,
170
+ defAdjMatrix
168
171
  };
package/utils.js CHANGED
@@ -1,25 +1,27 @@
1
- /** @internal */
2
- export const __toDot = (edges, undirected, ids) => {
3
- const [type, sep] = undirected ? ["graph", "--"] : ["digraph", "->"];
4
- const res = [`${type} g {`];
5
- for (let e of edges) {
6
- res.push(ids
7
- ? `"${ids[e[0]]}"${sep}"${ids[e[1]]}";`
8
- : `"${e[0]}"${sep}"${e[1]}";`);
9
- }
10
- res.push(`}`);
11
- return res.join("\n");
1
+ const __toDot = (edges, undirected, ids) => {
2
+ const [type, sep] = undirected ? ["graph", "--"] : ["digraph", "->"];
3
+ const res = [`${type} g {`];
4
+ for (let e of edges) {
5
+ res.push(
6
+ ids ? `"${ids[e[0]]}"${sep}"${ids[e[1]]}";` : `"${e[0]}"${sep}"${e[1]}";`
7
+ );
8
+ }
9
+ res.push(`}`);
10
+ return res.join("\n");
12
11
  };
13
- /** @internal */
14
- export const __into = (graph, edges) => {
15
- for (let e of edges) {
16
- graph.addEdge(e[0], e[1]);
17
- }
12
+ const __into = (graph, edges) => {
13
+ for (let e of edges) {
14
+ graph.addEdge(e[0], e[1]);
15
+ }
18
16
  };
19
- /** @internal */
20
- export const __invert = (graph, edges) => {
21
- for (let e of edges) {
22
- graph.addEdge(e[1], e[0]);
23
- }
24
- return graph;
17
+ const __invert = (graph, edges) => {
18
+ for (let e of edges) {
19
+ graph.addEdge(e[1], e[0]);
20
+ }
21
+ return graph;
22
+ };
23
+ export {
24
+ __into,
25
+ __invert,
26
+ __toDot
25
27
  };