@graphty/algorithms 2.0.2 → 2.0.4

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.
Files changed (48) hide show
  1. package/README.md +42 -43
  2. package/dist/algorithms.js +85 -47
  3. package/dist/algorithms.js.map +1 -1
  4. package/dist/algorithms.standalone.js +86 -48
  5. package/dist/algorithms.standalone.js.map +1 -1
  6. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +9 -3
  7. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
  8. package/dist/src/algorithms/centrality/delta-pagerank-simple.js +29 -31
  9. package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
  10. package/dist/src/algorithms/centrality/eigenvector.d.ts +6 -3
  11. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
  12. package/dist/src/algorithms/centrality/eigenvector.js +14 -5
  13. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
  14. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
  15. package/dist/src/algorithms/centrality/pagerank.js +7 -3
  16. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  17. package/dist/src/core/graph.d.ts.map +1 -1
  18. package/dist/src/core/graph.js +7 -3
  19. package/dist/src/core/graph.js.map +1 -1
  20. package/dist/src/errors.d.ts +22 -0
  21. package/dist/src/errors.d.ts.map +1 -1
  22. package/dist/src/errors.js +24 -0
  23. package/dist/src/errors.js.map +1 -1
  24. package/dist/src/index.d.ts +1 -1
  25. package/dist/src/index.d.ts.map +1 -1
  26. package/dist/src/index.js +1 -1
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/indexed/dijkstra.d.ts +2 -0
  29. package/dist/src/indexed/dijkstra.d.ts.map +1 -1
  30. package/dist/src/indexed/dijkstra.js +32 -13
  31. package/dist/src/indexed/dijkstra.js.map +1 -1
  32. package/dist/src/link-prediction/adamic-adar.js +1 -1
  33. package/dist/src/link-prediction/adamic-adar.js.map +1 -1
  34. package/dist/src/link-prediction/common-neighbors.js +1 -1
  35. package/dist/src/link-prediction/common-neighbors.js.map +1 -1
  36. package/dist/src/types/index.d.ts +4 -0
  37. package/dist/src/types/index.d.ts.map +1 -1
  38. package/package.json +3 -3
  39. package/src/algorithms/centrality/delta-pagerank-simple.ts +44 -33
  40. package/src/algorithms/centrality/eigenvector.ts +14 -5
  41. package/src/algorithms/centrality/pagerank.ts +9 -3
  42. package/src/core/graph.ts +8 -3
  43. package/src/errors.ts +29 -0
  44. package/src/index.ts +1 -1
  45. package/src/indexed/dijkstra.ts +33 -13
  46. package/src/link-prediction/adamic-adar.ts +1 -1
  47. package/src/link-prediction/common-neighbors.ts +1 -1
  48. package/src/types/index.ts +4 -0
@@ -1,5 +1,6 @@
1
1
  import { type AdjacencyView, INVALID_INDEX, type NumericVector, type U32 } from "@graphty/graph-format";
2
2
 
3
+ import { PathWalkError } from "../errors.js";
3
4
  import { arcSourceIn } from "./structures/arc-source.js";
4
5
  import { IndexedMinHeap } from "./structures/min-heap.js";
5
6
 
@@ -36,6 +37,33 @@ export interface SsspOptions {
36
37
  readonly weights?: NumericVector | undefined;
37
38
  }
38
39
 
40
+ /**
41
+ * The arcs from `target` back to `source`, target end first. `predArc` may come from an
42
+ * accelerator, so it is not trusted: a missing or out-of-range arc, or more than nodeCount - 1
43
+ * steps, throws rather than walking off the array or looping.
44
+ * @param g - The adjacency the search ran on
45
+ * @param predArc - The search's predecessor-arc array
46
+ * @param source - The search's source node index
47
+ * @param target - The node to walk back from (reached, and not the source)
48
+ * @returns Arc indices, target end first
49
+ */
50
+ function walkBack(g: AdjacencyView, predArc: U32, source: number, target: number): number[] {
51
+ const arcs: number[] = [];
52
+ let node = target;
53
+ while (node !== source) {
54
+ if (arcs.length >= g.nodeCount - 1) {
55
+ throw new PathWalkError(source, target, "cycle");
56
+ }
57
+ const arc = predArc[node];
58
+ if (!(arc < g.arcCount)) {
59
+ throw new PathWalkError(source, target, "gap"); // INVALID_INDEX is past arcCount too
60
+ }
61
+ arcs.push(arc);
62
+ node = arcSourceIn(g.rowPtr, arc);
63
+ }
64
+ return arcs;
65
+ }
66
+
39
67
  /**
40
68
  * Walk the predecessor arcs back from `target` and return the node path, source first.
41
69
  * @param g - The adjacency the search ran on
@@ -43,6 +71,7 @@ export interface SsspOptions {
43
71
  * @param source - The search's source node index
44
72
  * @param target - The node to walk back from
45
73
  * @returns Node indices from source to target inclusive, or an empty array when unreached
74
+ * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`
46
75
  * @public
47
76
  */
48
77
  export function walkPredArcs(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {
@@ -52,12 +81,7 @@ export function walkPredArcs(g: AdjacencyView, predArc: U32, source: number, tar
52
81
  if (predArc[target] === INVALID_INDEX) {
53
82
  return new Uint32Array(0);
54
83
  }
55
- const reversed: number[] = [target];
56
- let node = target;
57
- while (node !== source) {
58
- node = arcSourceIn(g.rowPtr, predArc[node]);
59
- reversed.push(node);
60
- }
84
+ const reversed = [target, ...walkBack(g, predArc, source, target).map((arc) => arcSourceIn(g.rowPtr, arc))];
61
85
  const out = new Uint32Array(reversed.length);
62
86
  for (let i = 0; i < reversed.length; i++) {
63
87
  out[i] = reversed[reversed.length - 1 - i];
@@ -72,19 +96,15 @@ export function walkPredArcs(g: AdjacencyView, predArc: U32, source: number, tar
72
96
  * @param source - The search's source node index
73
97
  * @param target - The node to walk back from
74
98
  * @returns Logical edge indices from source to target, or an empty array when unreached
99
+ * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`
75
100
  * @public
76
101
  */
77
102
  export function walkPredEdges(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {
78
103
  if (target === source || predArc[target] === INVALID_INDEX) {
79
104
  return new Uint32Array(0);
80
105
  }
81
- const reversed: number[] = [];
82
- let node = target;
83
- while (node !== source) {
84
- const arc = predArc[node];
85
- reversed.push(g.arcToEdge[arc]); // the EXACT parallel edge, not a (u, v) lookup
86
- node = arcSourceIn(g.rowPtr, arc);
87
- }
106
+ // the EXACT parallel edge, not a (u, v) lookup
107
+ const reversed = walkBack(g, predArc, source, target).map((arc) => g.arcToEdge[arc]);
88
108
  const out = new Uint32Array(reversed.length);
89
109
  for (let i = 0; i < reversed.length; i++) {
90
110
  out[i] = reversed[reversed.length - 1 - i];
@@ -78,7 +78,7 @@ export function adamicAdarPrediction(graph: Graph, options: LinkPredictionOption
78
78
  const source = nodes[i];
79
79
  const target = nodes[j];
80
80
 
81
- if (!source || !target) {
81
+ if (source === undefined || target === undefined) {
82
82
  continue;
83
83
  }
84
84
 
@@ -71,7 +71,7 @@ export function commonNeighborsPrediction(graph: Graph, options: LinkPredictionO
71
71
  const source = nodes[i];
72
72
  const target = nodes[j];
73
73
 
74
- if (!source || !target) {
74
+ if (source === undefined || target === undefined) {
75
75
  continue;
76
76
  }
77
77
 
@@ -24,6 +24,10 @@ export interface Node {
24
24
  export interface GraphConfig {
25
25
  directed: boolean;
26
26
  allowSelfLoops: boolean;
27
+ /**
28
+ * When true, adding an edge between a pair that already has one REPLACES that edge (its
29
+ * weight and data) instead of throwing. The graph never holds two edges for one pair.
30
+ */
27
31
  allowParallelEdges: boolean;
28
32
  }
29
33