@graphty/algorithms 2.0.3 → 2.0.5
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/README.md +2 -2
- package/dist/algorithms.js +85 -47
- package/dist/algorithms.js.map +1 -1
- package/dist/algorithms.standalone.js +97 -49
- package/dist/algorithms.standalone.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +9 -3
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +29 -31
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +6 -3
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.js +14 -5
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +7 -3
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +7 -3
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/errors.d.ts +22 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +24 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexed/dijkstra.d.ts +2 -0
- package/dist/src/indexed/dijkstra.d.ts.map +1 -1
- package/dist/src/indexed/dijkstra.js +32 -13
- package/dist/src/indexed/dijkstra.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.js +1 -1
- package/dist/src/link-prediction/adamic-adar.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +1 -1
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/types/index.d.ts +4 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/algorithms/centrality/delta-pagerank-simple.ts +44 -33
- package/src/algorithms/centrality/eigenvector.ts +14 -5
- package/src/algorithms/centrality/pagerank.ts +9 -3
- package/src/core/graph.ts +8 -3
- package/src/errors.ts +29 -0
- package/src/index.ts +1 -1
- package/src/indexed/dijkstra.ts +33 -13
- package/src/link-prediction/adamic-adar.ts +1 -1
- package/src/link-prediction/common-neighbors.ts +1 -1
- package/src/types/index.ts +4 -0
|
@@ -84,7 +84,8 @@ class Graph {
|
|
|
84
84
|
if (!this.config.allowSelfLoops && source === target) {
|
|
85
85
|
throw new Error("Self-loops are not allowed in this graph");
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
const replacing = this.hasEdge(source, target);
|
|
88
|
+
if (!this.config.allowParallelEdges && replacing) {
|
|
88
89
|
throw new Error("Parallel edges are not allowed in this graph");
|
|
89
90
|
}
|
|
90
91
|
const edge = { source, target, weight, data };
|
|
@@ -106,7 +107,9 @@ class Graph {
|
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
+
if (!replacing) {
|
|
111
|
+
this.edgeCount++;
|
|
112
|
+
}
|
|
110
113
|
this.mutations++;
|
|
111
114
|
}
|
|
112
115
|
/**
|
|
@@ -351,6 +354,23 @@ class ConvergenceError extends Error {
|
|
|
351
354
|
this.name = "ConvergenceError";
|
|
352
355
|
}
|
|
353
356
|
}
|
|
357
|
+
class PathWalkError extends Error {
|
|
358
|
+
/**
|
|
359
|
+
* Builds the error and its message.
|
|
360
|
+
* @param source - The search's source node index
|
|
361
|
+
* @param target - The node index the walk started from
|
|
362
|
+
* @param reason - `"gap"` or `"cycle"`, as above
|
|
363
|
+
*/
|
|
364
|
+
constructor(source, target, reason) {
|
|
365
|
+
super(
|
|
366
|
+
`cannot walk the shortest path from node ${String(source)} to node ${String(target)}: the predecessor array has a ${reason}`
|
|
367
|
+
);
|
|
368
|
+
this.source = source;
|
|
369
|
+
this.target = target;
|
|
370
|
+
this.reason = reason;
|
|
371
|
+
this.name = "PathWalkError";
|
|
372
|
+
}
|
|
373
|
+
}
|
|
354
374
|
var lib = {};
|
|
355
375
|
var SparseTypedFastBitSet = {};
|
|
356
376
|
var utils = {};
|
|
@@ -5252,7 +5272,7 @@ class PriorityDeltaPageRank {
|
|
|
5252
5272
|
}
|
|
5253
5273
|
}
|
|
5254
5274
|
function eigenvectorCentrality(graph, options = {}) {
|
|
5255
|
-
const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector } = options;
|
|
5275
|
+
const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector, mode = "in" } = options;
|
|
5256
5276
|
const nodeIds = Array.from(graph.nodes(), (node) => node.id);
|
|
5257
5277
|
const keys = nodeIds.map((id) => id.toString());
|
|
5258
5278
|
const n = keys.length;
|
|
@@ -5261,7 +5281,13 @@ function eigenvectorCentrality(graph, options = {}) {
|
|
|
5261
5281
|
return centrality;
|
|
5262
5282
|
}
|
|
5263
5283
|
const index2 = new Map(keys.map((key, i) => [key, i]));
|
|
5264
|
-
const
|
|
5284
|
+
const feeders = (id) => {
|
|
5285
|
+
if (!graph.isDirected || mode === "out") {
|
|
5286
|
+
return graph.neighbors(id);
|
|
5287
|
+
}
|
|
5288
|
+
return mode === "in" ? graph.inNeighbors(id) : /* @__PURE__ */ new Set([...graph.inNeighbors(id), ...graph.neighbors(id)]);
|
|
5289
|
+
};
|
|
5290
|
+
const adjacency = nodeIds.map((id) => Array.from(feeders(id), (m) => index2.get(m.toString()) ?? 0));
|
|
5265
5291
|
if (isNilpotent(adjacency)) {
|
|
5266
5292
|
for (const key of keys) {
|
|
5267
5293
|
centrality[key] = 0;
|
|
@@ -5549,6 +5575,8 @@ class SimpleDeltaPageRank {
|
|
|
5549
5575
|
*/
|
|
5550
5576
|
constructor(graph) {
|
|
5551
5577
|
this.previousScores = null;
|
|
5578
|
+
this.iterations = 0;
|
|
5579
|
+
this.converged = false;
|
|
5552
5580
|
if (!graph.isDirected) {
|
|
5553
5581
|
throw new Error("PageRank requires a directed graph");
|
|
5554
5582
|
}
|
|
@@ -5561,20 +5589,32 @@ class SimpleDeltaPageRank {
|
|
|
5561
5589
|
* @param options.dampingFactor - Probability of following a link (default: 0.85)
|
|
5562
5590
|
* @param options.tolerance - Convergence tolerance threshold (default: 1e-6)
|
|
5563
5591
|
* @param options.maxIterations - Maximum number of iterations (default: 100)
|
|
5592
|
+
* @param options.initialRanks - Starting scores (missing nodes start at 1/n; normalized to sum 1)
|
|
5564
5593
|
* @param options.personalization - Personalization vector for Personalized PageRank
|
|
5565
5594
|
* @param options.weight - Edge attribute name for weighted PageRank
|
|
5566
|
-
* @returns Map of node IDs to their PageRank scores
|
|
5595
|
+
* @returns Map of node IDs to their PageRank scores; `iterations` and `converged` describe the run
|
|
5567
5596
|
*/
|
|
5568
5597
|
compute(options = {}) {
|
|
5569
|
-
const {
|
|
5598
|
+
const {
|
|
5599
|
+
dampingFactor = 0.85,
|
|
5600
|
+
tolerance = 1e-6,
|
|
5601
|
+
maxIterations = 100,
|
|
5602
|
+
initialRanks,
|
|
5603
|
+
personalization,
|
|
5604
|
+
weight
|
|
5605
|
+
} = options;
|
|
5606
|
+
this.iterations = 0;
|
|
5607
|
+
this.converged = false;
|
|
5570
5608
|
if (this.nodeCount === 0) {
|
|
5609
|
+
this.converged = true;
|
|
5571
5610
|
return /* @__PURE__ */ new Map();
|
|
5572
5611
|
}
|
|
5573
5612
|
const scores = /* @__PURE__ */ new Map();
|
|
5574
5613
|
const newScores = /* @__PURE__ */ new Map();
|
|
5575
5614
|
for (const node of this.graph.nodes()) {
|
|
5576
|
-
scores.set(node.id, 1 / this.nodeCount);
|
|
5615
|
+
scores.set(node.id, initialRanks?.get(node.id) ?? 1 / this.nodeCount);
|
|
5577
5616
|
}
|
|
5617
|
+
this.normalizeMap(scores);
|
|
5578
5618
|
const outWeights = /* @__PURE__ */ new Map();
|
|
5579
5619
|
const danglingNodes = /* @__PURE__ */ new Set();
|
|
5580
5620
|
for (const node of this.graph.nodes()) {
|
|
@@ -5582,8 +5622,7 @@ class SimpleDeltaPageRank {
|
|
|
5582
5622
|
let outDegree = 0;
|
|
5583
5623
|
for (const neighbor of Array.from(this.graph.neighbors(node.id))) {
|
|
5584
5624
|
outDegree++;
|
|
5585
|
-
|
|
5586
|
-
totalWeight += edge?.weight ?? 1;
|
|
5625
|
+
totalWeight += weight ? this.graph.getEdge(node.id, neighbor)?.weight ?? 1 : 1;
|
|
5587
5626
|
}
|
|
5588
5627
|
outWeights.set(node.id, totalWeight);
|
|
5589
5628
|
if (outDegree === 0) {
|
|
@@ -5595,7 +5634,6 @@ class SimpleDeltaPageRank {
|
|
|
5595
5634
|
personalVector = new Map(personalization);
|
|
5596
5635
|
this.normalizeMap(personalVector);
|
|
5597
5636
|
}
|
|
5598
|
-
let activeNodes = new Set(scores.keys());
|
|
5599
5637
|
let iteration = 0;
|
|
5600
5638
|
for (iteration = 0; iteration < maxIterations; iteration++) {
|
|
5601
5639
|
for (const nodeId of scores.keys()) {
|
|
@@ -5621,7 +5659,7 @@ class SimpleDeltaPageRank {
|
|
|
5621
5659
|
}
|
|
5622
5660
|
}
|
|
5623
5661
|
}
|
|
5624
|
-
for (const nodeId of
|
|
5662
|
+
for (const nodeId of scores.keys()) {
|
|
5625
5663
|
const currentRank = scores.get(nodeId) ?? 0;
|
|
5626
5664
|
const nodeOutWeight = outWeights.get(nodeId) ?? 0;
|
|
5627
5665
|
if (nodeOutWeight > 0) {
|
|
@@ -5637,33 +5675,21 @@ class SimpleDeltaPageRank {
|
|
|
5637
5675
|
}
|
|
5638
5676
|
}
|
|
5639
5677
|
}
|
|
5640
|
-
const nextActive = /* @__PURE__ */ new Set();
|
|
5641
5678
|
let maxDiff = 0;
|
|
5642
5679
|
for (const nodeId of scores.keys()) {
|
|
5643
|
-
|
|
5644
|
-
const newRank = newScores.get(nodeId) ?? 0;
|
|
5645
|
-
const diff = Math.abs(newRank - oldRank);
|
|
5646
|
-
maxDiff = Math.max(maxDiff, diff);
|
|
5647
|
-
if (diff > tolerance / 10) {
|
|
5648
|
-
nextActive.add(nodeId);
|
|
5649
|
-
for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
|
|
5650
|
-
nextActive.add(neighbor);
|
|
5651
|
-
}
|
|
5652
|
-
for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {
|
|
5653
|
-
nextActive.add(neighbor);
|
|
5654
|
-
}
|
|
5655
|
-
}
|
|
5680
|
+
maxDiff = Math.max(maxDiff, Math.abs((newScores.get(nodeId) ?? 0) - (scores.get(nodeId) ?? 0)));
|
|
5656
5681
|
}
|
|
5657
5682
|
scores.clear();
|
|
5658
5683
|
for (const [k, v] of newScores) {
|
|
5659
5684
|
scores.set(k, v);
|
|
5660
5685
|
}
|
|
5661
5686
|
newScores.clear();
|
|
5662
|
-
activeNodes = nextActive;
|
|
5663
5687
|
if (maxDiff < tolerance) {
|
|
5688
|
+
this.converged = true;
|
|
5664
5689
|
break;
|
|
5665
5690
|
}
|
|
5666
5691
|
}
|
|
5692
|
+
this.iterations = this.converged ? iteration + 1 : iteration;
|
|
5667
5693
|
this.previousScores = new Map(scores);
|
|
5668
5694
|
return scores;
|
|
5669
5695
|
}
|
|
@@ -5684,6 +5710,8 @@ class SimpleDeltaPageRank {
|
|
|
5684
5710
|
return this.compute(options);
|
|
5685
5711
|
}
|
|
5686
5712
|
const { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;
|
|
5713
|
+
this.iterations = 0;
|
|
5714
|
+
this.converged = false;
|
|
5687
5715
|
const scores = new Map(this.previousScores);
|
|
5688
5716
|
const newScores = /* @__PURE__ */ new Map();
|
|
5689
5717
|
for (const node of this.graph.nodes()) {
|
|
@@ -5708,8 +5736,7 @@ class SimpleDeltaPageRank {
|
|
|
5708
5736
|
let outDegree = 0;
|
|
5709
5737
|
for (const neighbor of Array.from(this.graph.neighbors(node.id))) {
|
|
5710
5738
|
outDegree++;
|
|
5711
|
-
|
|
5712
|
-
totalWeight += edge?.weight ?? 1;
|
|
5739
|
+
totalWeight += weight ? this.graph.getEdge(node.id, neighbor)?.weight ?? 1 : 1;
|
|
5713
5740
|
}
|
|
5714
5741
|
outWeights.set(node.id, totalWeight);
|
|
5715
5742
|
if (outDegree === 0) {
|
|
@@ -5786,9 +5813,11 @@ class SimpleDeltaPageRank {
|
|
|
5786
5813
|
newScores.clear();
|
|
5787
5814
|
activeNodes = nextActive;
|
|
5788
5815
|
if (maxDiff < tolerance) {
|
|
5816
|
+
this.converged = true;
|
|
5789
5817
|
break;
|
|
5790
5818
|
}
|
|
5791
5819
|
}
|
|
5820
|
+
this.iterations = this.converged ? iteration + 1 : iteration;
|
|
5792
5821
|
this.previousScores = new Map(scores);
|
|
5793
5822
|
return scores;
|
|
5794
5823
|
}
|
|
@@ -5831,6 +5860,9 @@ function pageRank$1(graph, options = {}) {
|
|
|
5831
5860
|
tolerance,
|
|
5832
5861
|
maxIterations
|
|
5833
5862
|
};
|
|
5863
|
+
if (initialRanks) {
|
|
5864
|
+
deltaOptions.initialRanks = initialRanks;
|
|
5865
|
+
}
|
|
5834
5866
|
if (personalization) {
|
|
5835
5867
|
deltaOptions.personalization = personalization;
|
|
5836
5868
|
}
|
|
@@ -5845,9 +5877,8 @@ function pageRank$1(graph, options = {}) {
|
|
|
5845
5877
|
}
|
|
5846
5878
|
return {
|
|
5847
5879
|
ranks: result2,
|
|
5848
|
-
iterations:
|
|
5849
|
-
|
|
5850
|
-
converged: true
|
|
5880
|
+
iterations: deltaPageRank.iterations,
|
|
5881
|
+
converged: deltaPageRank.converged
|
|
5851
5882
|
};
|
|
5852
5883
|
}
|
|
5853
5884
|
let ranks = /* @__PURE__ */ new Map();
|
|
@@ -5949,7 +5980,8 @@ function pageRank$1(graph, options = {}) {
|
|
|
5949
5980
|
}
|
|
5950
5981
|
return {
|
|
5951
5982
|
ranks: result,
|
|
5952
|
-
|
|
5983
|
+
// The loop breaks before incrementing on convergence, and leaves at maxIterations otherwise.
|
|
5984
|
+
iterations: converged ? iteration + 1 : iteration,
|
|
5953
5985
|
converged
|
|
5954
5986
|
};
|
|
5955
5987
|
}
|
|
@@ -10121,7 +10153,7 @@ function adamicAdarPrediction(graph, options = {}) {
|
|
|
10121
10153
|
for (let j = i + 1; j < nodes.length; j++) {
|
|
10122
10154
|
const source = nodes[i];
|
|
10123
10155
|
const target = nodes[j];
|
|
10124
|
-
if (
|
|
10156
|
+
if (source === void 0 || target === void 0) {
|
|
10125
10157
|
continue;
|
|
10126
10158
|
}
|
|
10127
10159
|
if (!includeExisting && graph.hasEdge(source, target)) {
|
|
@@ -10299,7 +10331,7 @@ function commonNeighborsPrediction(graph, options = {}) {
|
|
|
10299
10331
|
for (let j = i + 1; j < nodes.length; j++) {
|
|
10300
10332
|
const source = nodes[i];
|
|
10301
10333
|
const target = nodes[j];
|
|
10302
|
-
if (
|
|
10334
|
+
if (source === void 0 || target === void 0) {
|
|
10303
10335
|
continue;
|
|
10304
10336
|
}
|
|
10305
10337
|
if (!includeExisting && graph.hasEdge(source, target)) {
|
|
@@ -18444,7 +18476,7 @@ function checkUniqueColumn(table, column) {
|
|
|
18444
18476
|
throw err;
|
|
18445
18477
|
}
|
|
18446
18478
|
}
|
|
18447
|
-
const WIRE_PRODUCER = `@graphty/graph-format@${"
|
|
18479
|
+
const WIRE_PRODUCER = `@graphty/graph-format@${"0f6f0f1500bd"}`;
|
|
18448
18480
|
const SCALAR_VIEWS = /* @__PURE__ */ new Set(["totalWeight", "symmetric"]);
|
|
18449
18481
|
const encoder = new TextEncoder();
|
|
18450
18482
|
function assertLittleEndianHost(littleEndian = IS_LITTLE_ENDIAN) {
|
|
@@ -22192,7 +22224,9 @@ class GraphBuilder {
|
|
|
22192
22224
|
return this.staging.edgeBound;
|
|
22193
22225
|
}
|
|
22194
22226
|
/**
|
|
22195
|
-
* Increments on every
|
|
22227
|
+
* Increments on every change that makes the next freeze() differ (topology, weights, cell and
|
|
22228
|
+
* column writes, declarations, graph values, meta, extension tables, record and graph merges);
|
|
22229
|
+
* freeze() itself does not count.
|
|
22196
22230
|
* @returns the count
|
|
22197
22231
|
*/
|
|
22198
22232
|
get mutationCount() {
|
|
@@ -22751,6 +22785,7 @@ class GraphBuilder {
|
|
|
22751
22785
|
buildGraphColumn(name, value, patch);
|
|
22752
22786
|
}
|
|
22753
22787
|
this.graphValues.set(name, { decl: patch, value });
|
|
22788
|
+
this.mutated();
|
|
22754
22789
|
}
|
|
22755
22790
|
/**
|
|
22756
22791
|
* Merge fields into the graph metadata (design section 5.9); undefined fields are left alone,
|
|
@@ -22760,6 +22795,7 @@ class GraphBuilder {
|
|
|
22760
22795
|
setMeta(meta) {
|
|
22761
22796
|
this.check();
|
|
22762
22797
|
this.metaValue = resolveGraphMeta$1(this.metaValue, meta);
|
|
22798
|
+
this.mutated();
|
|
22763
22799
|
}
|
|
22764
22800
|
/**
|
|
22765
22801
|
* Create an extension table (design section 5.10).
|
|
@@ -22786,6 +22822,7 @@ class GraphBuilder {
|
|
|
22786
22822
|
columns.push(column);
|
|
22787
22823
|
}
|
|
22788
22824
|
staging.extensions.push({ name, columns, rowCount: 0 });
|
|
22825
|
+
this.mutated();
|
|
22789
22826
|
return staging.extensions.length - 1;
|
|
22790
22827
|
}
|
|
22791
22828
|
/**
|
|
@@ -22814,6 +22851,7 @@ class GraphBuilder {
|
|
|
22814
22851
|
target.columns[i].write(row, checked[i]);
|
|
22815
22852
|
}
|
|
22816
22853
|
target.rowCount = row + 1;
|
|
22854
|
+
this.mutated();
|
|
22817
22855
|
return row;
|
|
22818
22856
|
}
|
|
22819
22857
|
/**
|
|
@@ -22977,6 +23015,7 @@ class GraphBuilder {
|
|
|
22977
23015
|
for (const [name, table] of snapshot.extensions) {
|
|
22978
23016
|
this.appendExtension(name, table, refs);
|
|
22979
23017
|
}
|
|
23018
|
+
this.mutated();
|
|
22980
23019
|
}
|
|
22981
23020
|
// ---------------------------------------------------------------- output and lifecycle
|
|
22982
23021
|
/**
|
|
@@ -23387,6 +23426,7 @@ class GraphBuilder {
|
|
|
23387
23426
|
return existing;
|
|
23388
23427
|
}
|
|
23389
23428
|
const columns = this.columnsOf(domain);
|
|
23429
|
+
this.mutated();
|
|
23390
23430
|
return this.pushColumn(columns, new StagingColumn(meta, false));
|
|
23391
23431
|
}
|
|
23392
23432
|
/**
|
|
@@ -23623,6 +23663,7 @@ class GraphBuilder {
|
|
|
23623
23663
|
if (widened !== null) {
|
|
23624
23664
|
this.widenings.push({ column: target.meta.name, domain, from: widened.from, to: widened.to });
|
|
23625
23665
|
}
|
|
23666
|
+
this.mutated();
|
|
23626
23667
|
}
|
|
23627
23668
|
/**
|
|
23628
23669
|
* Replace or create a column from a typed array (setNodeColumn / setEdgeColumn).
|
|
@@ -23649,6 +23690,7 @@ class GraphBuilder {
|
|
|
23649
23690
|
} else {
|
|
23650
23691
|
this.pushColumn(columns, column);
|
|
23651
23692
|
}
|
|
23693
|
+
this.mutated();
|
|
23652
23694
|
}
|
|
23653
23695
|
extensionOf(handle) {
|
|
23654
23696
|
const { extensions } = this.staging;
|
|
@@ -24202,6 +24244,22 @@ class IndexedMinHeap {
|
|
|
24202
24244
|
this.slot[node] = at;
|
|
24203
24245
|
}
|
|
24204
24246
|
}
|
|
24247
|
+
function walkBack(g, predArc, source, target) {
|
|
24248
|
+
const arcs = [];
|
|
24249
|
+
let node = target;
|
|
24250
|
+
while (node !== source) {
|
|
24251
|
+
if (arcs.length >= g.nodeCount - 1) {
|
|
24252
|
+
throw new PathWalkError(source, target, "cycle");
|
|
24253
|
+
}
|
|
24254
|
+
const arc = predArc[node];
|
|
24255
|
+
if (!(arc < g.arcCount)) {
|
|
24256
|
+
throw new PathWalkError(source, target, "gap");
|
|
24257
|
+
}
|
|
24258
|
+
arcs.push(arc);
|
|
24259
|
+
node = arcSourceIn(g.rowPtr, arc);
|
|
24260
|
+
}
|
|
24261
|
+
return arcs;
|
|
24262
|
+
}
|
|
24205
24263
|
function walkPredArcs(g, predArc, source, target) {
|
|
24206
24264
|
if (target === source) {
|
|
24207
24265
|
return Uint32Array.of(source);
|
|
@@ -24209,12 +24267,7 @@ function walkPredArcs(g, predArc, source, target) {
|
|
|
24209
24267
|
if (predArc[target] === INVALID_INDEX) {
|
|
24210
24268
|
return new Uint32Array(0);
|
|
24211
24269
|
}
|
|
24212
|
-
const reversed = [target];
|
|
24213
|
-
let node = target;
|
|
24214
|
-
while (node !== source) {
|
|
24215
|
-
node = arcSourceIn(g.rowPtr, predArc[node]);
|
|
24216
|
-
reversed.push(node);
|
|
24217
|
-
}
|
|
24270
|
+
const reversed = [target, ...walkBack(g, predArc, source, target).map((arc) => arcSourceIn(g.rowPtr, arc))];
|
|
24218
24271
|
const out = new Uint32Array(reversed.length);
|
|
24219
24272
|
for (let i = 0; i < reversed.length; i++) {
|
|
24220
24273
|
out[i] = reversed[reversed.length - 1 - i];
|
|
@@ -24225,13 +24278,7 @@ function walkPredEdges(g, predArc, source, target) {
|
|
|
24225
24278
|
if (target === source || predArc[target] === INVALID_INDEX) {
|
|
24226
24279
|
return new Uint32Array(0);
|
|
24227
24280
|
}
|
|
24228
|
-
const reversed = [];
|
|
24229
|
-
let node = target;
|
|
24230
|
-
while (node !== source) {
|
|
24231
|
-
const arc = predArc[node];
|
|
24232
|
-
reversed.push(g.arcToEdge[arc]);
|
|
24233
|
-
node = arcSourceIn(g.rowPtr, arc);
|
|
24234
|
-
}
|
|
24281
|
+
const reversed = walkBack(g, predArc, source, target).map((arc) => g.arcToEdge[arc]);
|
|
24235
24282
|
const out = new Uint32Array(reversed.length);
|
|
24236
24283
|
for (let i = 0; i < reversed.length; i++) {
|
|
24237
24284
|
out[i] = reversed[reversed.length - 1 - i];
|
|
@@ -24409,6 +24456,7 @@ export {
|
|
|
24409
24456
|
DirectionOptimizedBFS,
|
|
24410
24457
|
Graph,
|
|
24411
24458
|
GraphBitSet,
|
|
24459
|
+
PathWalkError,
|
|
24412
24460
|
PriorityDeltaPageRank,
|
|
24413
24461
|
PriorityQueue,
|
|
24414
24462
|
UnionFind,
|