@graphty/algorithms 1.7.0 → 1.7.2

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 (37) hide show
  1. package/dist/algorithms.js +19 -18
  2. package/dist/algorithms.js.map +1 -1
  3. package/dist/src/algorithms/community/louvain-optimized.d.ts +1 -1
  4. package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
  5. package/dist/src/clustering/spectral.d.ts +1 -0
  6. package/dist/src/clustering/spectral.d.ts.map +1 -1
  7. package/dist/src/clustering/spectral.js +18 -13
  8. package/dist/src/clustering/spectral.js.map +1 -1
  9. package/dist/src/optimized/direction-optimized-bfs.d.ts +3 -10
  10. package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
  11. package/dist/src/optimized/direction-optimized-bfs.js +0 -11
  12. package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
  13. package/dist/tsconfig.tsbuildinfo +1 -1
  14. package/package.json +2 -4
  15. package/src/algorithms/community/louvain-optimized.ts +1 -1
  16. package/src/clustering/spectral.ts +20 -10
  17. package/src/optimized/direction-optimized-bfs.ts +2 -17
  18. package/dist/src/utils/algorithm-utilities.d.ts +0 -2
  19. package/dist/src/utils/algorithm-utilities.d.ts.map +0 -1
  20. package/dist/src/utils/algorithm-utilities.js +0 -2
  21. package/dist/src/utils/algorithm-utilities.js.map +0 -1
  22. package/dist/src/utils/index.d.ts +0 -5
  23. package/dist/src/utils/index.d.ts.map +0 -1
  24. package/dist/src/utils/index.js +0 -5
  25. package/dist/src/utils/index.js.map +0 -1
  26. package/dist/src/utils/matrix-utilities.d.ts +0 -2
  27. package/dist/src/utils/matrix-utilities.d.ts.map +0 -1
  28. package/dist/src/utils/matrix-utilities.js +0 -2
  29. package/dist/src/utils/matrix-utilities.js.map +0 -1
  30. package/dist/src/utils/optimization-helpers.d.ts +0 -42
  31. package/dist/src/utils/optimization-helpers.d.ts.map +0 -1
  32. package/dist/src/utils/optimization-helpers.js +0 -59
  33. package/dist/src/utils/optimization-helpers.js.map +0 -1
  34. package/src/utils/algorithm-utilities.ts +0 -2
  35. package/src/utils/index.ts +0 -4
  36. package/src/utils/matrix-utilities.ts +0 -2
  37. package/src/utils/optimization-helpers.ts +0 -87
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphty/algorithms",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "Graph algorithms library for browser environments implemented in TypeScript",
5
5
  "author": "Adam Powers <apowers@ato.ms>",
6
6
  "main": "dist/algorithms.js",
@@ -88,7 +88,6 @@
88
88
  "vitest": "^3.2.4"
89
89
  },
90
90
  "dependencies": {
91
- "pupt": "^1.3.2",
92
91
  "typedfastbitset": "^0.6.1"
93
92
  },
94
93
  "scripts": {
@@ -117,8 +116,7 @@
117
116
  "memory:profile": "tsx test/helpers/memory-profiler.ts",
118
117
  "lint": "eslint && tsc --noEmit",
119
118
  "lint:fix": "eslint --fix",
120
- "lint:pkg": "knip",
121
- "lint:all": "npm run lint && npm run lint:pkg",
119
+ "lint:knip": "cd .. && pnpm run lint:knip -- --workspace algorithms",
122
120
  "typecheck": "tsc --noEmit",
123
121
  "build": "tsc",
124
122
  "build:bundle": "node scripts/build-bundle.js",
@@ -13,7 +13,7 @@ import type { CommunityResult, NodeId } from "../../types/index.js";
13
13
  * Expected speedup: 2-5x on large graphs with many leaf nodes
14
14
  */
15
15
 
16
- export interface OptimizedLouvainOptions {
16
+ interface OptimizedLouvainOptions {
17
17
  /**
18
18
  * Resolution parameter (default: 1.0)
19
19
  */
@@ -1,6 +1,6 @@
1
1
  import type { Graph } from "../core/graph.js";
2
2
  import type { NodeId } from "../types/index.js";
3
- import { euclideanDistance } from "../utils/math-utilities.js";
3
+ import { euclideanDistance, SeededRandom } from "../utils/math-utilities.js";
4
4
 
5
5
  /**
6
6
  * Spectral Clustering implementation
@@ -17,6 +17,7 @@ export interface SpectralClusteringOptions {
17
17
  laplacianType?: "unnormalized" | "normalized" | "randomWalk"; // Type of Laplacian
18
18
  maxIterations?: number; // Max iterations for k-means (default: 100)
19
19
  tolerance?: number; // Convergence tolerance (default: 1e-4)
20
+ seed?: number; // Random seed for reproducible results
20
21
  }
21
22
 
22
23
  export interface SpectralClusteringResult {
@@ -41,7 +42,10 @@ export interface SpectralClusteringResult {
41
42
  * @returns Spectral clustering result with communities and cluster assignments
42
43
  */
43
44
  export function spectralClustering(graph: Graph, options: SpectralClusteringOptions): SpectralClusteringResult {
44
- const { k, laplacianType = "normalized", maxIterations = 100, tolerance = 1e-4 } = options;
45
+ const { k, laplacianType = "normalized", maxIterations = 100, tolerance = 1e-4, seed } = options;
46
+
47
+ // Create random function - use seeded PRNG if seed provided, otherwise Math.random
48
+ const random = seed !== undefined ? SeededRandom.createGenerator(seed) : Math.random;
45
49
 
46
50
  // Input validation
47
51
  if (k < 1 || !Number.isInteger(k)) {
@@ -67,7 +71,7 @@ export function spectralClustering(graph: Graph, options: SpectralClusteringOpti
67
71
  const laplacianMatrix = buildLaplacianMatrix(adjacencyMatrix, laplacianType);
68
72
 
69
73
  // Find k smallest eigenvectors
70
- const eigenResult = findSmallestEigenvectors(laplacianMatrix, k);
74
+ const eigenResult = findSmallestEigenvectors(laplacianMatrix, k, random);
71
75
 
72
76
  // Perform k-means clustering on the eigenvectors
73
77
  // For spectral clustering, we need to transpose the eigenvector matrix
@@ -89,7 +93,7 @@ export function spectralClustering(graph: Graph, options: SpectralClusteringOpti
89
93
  normalizeRows(dataPoints);
90
94
  }
91
95
 
92
- const kmeans = kMeansClustering(dataPoints, k, maxIterations, tolerance);
96
+ const kmeans = kMeansClustering(dataPoints, k, maxIterations, tolerance, random);
93
97
 
94
98
  // Build communities
95
99
  const communities: NodeId[][] = Array.from({ length: k }, () => []);
@@ -293,11 +297,13 @@ function buildLaplacianMatrix(adjacency: number[][], type: string): number[][] {
293
297
  * This is a simplified implementation - in practice, you'd use LAPACK or similar
294
298
  * @param matrix - The Laplacian matrix for eigendecomposition
295
299
  * @param k - Number of smallest eigenvectors to find
300
+ * @param random - Random number generator function
296
301
  * @returns Object containing eigenvalues and corresponding eigenvectors
297
302
  */
298
303
  function findSmallestEigenvectors(
299
304
  matrix: number[][],
300
305
  k: number,
306
+ random: () => number,
301
307
  ): {
302
308
  eigenvalues: number[];
303
309
  eigenvectors: number[][];
@@ -318,7 +324,7 @@ function findSmallestEigenvectors(
318
324
  // For spectral clustering, we need proper eigenvectors
319
325
  // Special handling for small k values which are common in clustering
320
326
  if (k <= 3 && n > k) {
321
- return computeSmallestEigenvectorsSimple(matrix, k, n);
327
+ return computeSmallestEigenvectorsSimple(matrix, k, n, random);
322
328
  }
323
329
 
324
330
  // For larger k, use power iteration
@@ -330,7 +336,7 @@ function findSmallestEigenvectors(
330
336
  // Initialize random vector
331
337
  let vector = Array(n)
332
338
  .fill(0)
333
- .map(() => Math.random() - 0.5);
339
+ .map(() => random() - 0.5);
334
340
 
335
341
  // Normalize initial vector
336
342
  const initNorm = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
@@ -447,6 +453,7 @@ function normalizeRows(matrix: number[][]): void {
447
453
  * @param k - Number of clusters to form
448
454
  * @param maxIterations - Maximum number of iterations
449
455
  * @param tolerance - Convergence tolerance for centroid movement
456
+ * @param random - Random number generator function
450
457
  * @returns Object containing cluster assignments and final centroids
451
458
  */
452
459
  function kMeansClustering(
@@ -454,6 +461,7 @@ function kMeansClustering(
454
461
  k: number,
455
462
  maxIterations: number,
456
463
  tolerance = 1e-4,
464
+ random: () => number = Math.random,
457
465
  ): { assignments: number[]; centroids: number[][] } {
458
466
  const n = data.length;
459
467
  const d = data[0]?.length ?? 0;
@@ -476,7 +484,7 @@ function kMeansClustering(
476
484
  const selectedIndices = new Set<number>();
477
485
 
478
486
  while (centroids.length < k && selectedIndices.size < n) {
479
- const idx = Math.floor(Math.random() * n);
487
+ const idx = Math.floor(random() * n);
480
488
  if (!selectedIndices.has(idx) && data[idx]) {
481
489
  selectedIndices.add(idx);
482
490
  centroids.push([...data[idx]]);
@@ -487,7 +495,7 @@ function kMeansClustering(
487
495
  while (centroids.length < k) {
488
496
  const centroid = Array(d).fill(0) as number[];
489
497
  for (let j = 0; j < d; j++) {
490
- centroid[j] = Math.random() - 0.5;
498
+ centroid[j] = random() - 0.5;
491
499
  }
492
500
  centroids.push(centroid);
493
501
  }
@@ -611,12 +619,14 @@ function kMeansClustering(
611
619
  * @param matrix - The Laplacian matrix
612
620
  * @param k - Number of eigenvectors to compute (1-3)
613
621
  * @param n - Size of the matrix
622
+ * @param random - Random number generator function
614
623
  * @returns Object containing eigenvalues and eigenvectors
615
624
  */
616
625
  function computeSmallestEigenvectorsSimple(
617
626
  matrix: number[][],
618
627
  k: number,
619
628
  n: number,
629
+ random: () => number,
620
630
  ): {
621
631
  eigenvalues: number[];
622
632
  eigenvectors: number[][];
@@ -635,7 +645,7 @@ function computeSmallestEigenvectorsSimple(
635
645
  const maxEig = 2; // For normalized Laplacian, max eigenvalue <= 2
636
646
  let vector = Array(n)
637
647
  .fill(0)
638
- .map(() => Math.random() - 0.5);
648
+ .map(() => random() - 0.5);
639
649
 
640
650
  // Make orthogonal to first eigenvector
641
651
  const dot1 = vector.reduce((sum, val) => sum + val / Math.sqrt(n), 0);
@@ -681,7 +691,7 @@ function computeSmallestEigenvectorsSimple(
681
691
  if (k >= 3) {
682
692
  let vector = Array(n)
683
693
  .fill(0)
684
- .map(() => Math.random() - 0.5);
694
+ .map(() => random() - 0.5);
685
695
 
686
696
  // Orthogonalize against previous eigenvectors
687
697
  for (const prev of eigenvectors) {
@@ -5,7 +5,7 @@ import { CSRGraph } from "./csr-graph.js";
5
5
  /**
6
6
  * Options for Direction-Optimized BFS
7
7
  */
8
- export interface DirectionOptimizedBFSOptions {
8
+ interface DirectionOptimizedBFSOptions {
9
9
  alpha?: number; // Default: 15 - Controls top-down to bottom-up switch
10
10
  beta?: number; // Default: 18 - Controls bottom-up to top-down switch
11
11
  }
@@ -13,7 +13,7 @@ export interface DirectionOptimizedBFSOptions {
13
13
  /**
14
14
  * Result of BFS traversal
15
15
  */
16
- export interface BFSResult<TNodeId> {
16
+ interface BFSResult<TNodeId> {
17
17
  distances: Map<TNodeId, number>;
18
18
  parents: Map<TNodeId, TNodeId | null>;
19
19
  visitedCount: number;
@@ -293,18 +293,3 @@ export function directionOptimizedBFS<TNodeId = NodeId>(
293
293
  return bfs.search(source);
294
294
  }
295
295
 
296
- /**
297
- * Convenience function for multi-source BFS.
298
- * @param graph - The CSR graph to perform BFS on
299
- * @param sources - Array of source node IDs to start the BFS from
300
- * @param options - Optional configuration for switching thresholds
301
- * @returns The BFS result containing distances and parent pointers
302
- */
303
- export function directionOptimizedBFSMultiple<TNodeId = NodeId>(
304
- graph: CSRGraph<TNodeId>,
305
- sources: TNodeId[],
306
- options?: DirectionOptimizedBFSOptions,
307
- ): BFSResult<TNodeId> {
308
- const bfs = new DirectionOptimizedBFS(graph, options);
309
- return bfs.searchMultiple(sources);
310
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=algorithm-utilities.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"algorithm-utilities.d.ts","sourceRoot":"","sources":["../../../src/utils/algorithm-utilities.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=algorithm-utilities.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"algorithm-utilities.js","sourceRoot":"","sources":["../../../src/utils/algorithm-utilities.ts"],"names":[],"mappings":""}
@@ -1,5 +0,0 @@
1
- export * from "./algorithm-utilities.js";
2
- export * from "./graph-utilities.js";
3
- export * from "./math-utilities.js";
4
- export * from "./matrix-utilities.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
@@ -1,5 +0,0 @@
1
- export * from "./algorithm-utilities.js";
2
- export * from "./graph-utilities.js";
3
- export * from "./math-utilities.js";
4
- export * from "./matrix-utilities.js";
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=matrix-utilities.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"matrix-utilities.d.ts","sourceRoot":"","sources":["../../../src/utils/matrix-utilities.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=matrix-utilities.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"matrix-utilities.js","sourceRoot":"","sources":["../../../src/utils/matrix-utilities.ts"],"names":[],"mappings":""}
@@ -1,42 +0,0 @@
1
- import type { Graph } from "../core/graph.js";
2
- /**
3
- * Common interface for algorithm options with optimization support
4
- */
5
- export interface OptimizableOptions {
6
- /**
7
- * Whether to use optimized implementations
8
- * - true: Force use of optimizations
9
- * - false: Disable optimizations
10
- * - "auto": Automatically decide based on graph size (default)
11
- */
12
- optimized?: boolean | "auto";
13
- }
14
- /**
15
- * Determine if optimizations should be used for a given graph
16
- * @param graph - The graph to check for optimization eligibility
17
- * @param options - Options containing the optimization preference
18
- * @returns True if optimizations should be used for this graph
19
- */
20
- export declare function shouldOptimize(graph: Graph, options?: OptimizableOptions): boolean;
21
- /**
22
- * Merge optimization options with algorithm-specific options
23
- * @param graph - The graph to determine optimization settings for
24
- * @param options - Algorithm options that may include optimization settings
25
- * @returns The options with resolved optimization boolean flag
26
- */
27
- export declare function mergeOptimizationOptions<T extends Record<string, unknown>>(graph: Graph, options: T & OptimizableOptions): T & {
28
- optimized?: boolean;
29
- };
30
- /**
31
- * Create an optimized version of an algorithm
32
- * @param algorithm - The algorithm function to wrap with optimization support
33
- * @param optionsTransformer - Optional function to transform options before passing to the algorithm
34
- * @returns A wrapped version of the algorithm that applies optimization transformations
35
- * @example
36
- * const optimizedBetweenness = createOptimizedAlgorithm(
37
- * betweennessCentrality,
38
- * (graph, options) => ({...options, optimized: true})
39
- * );
40
- */
41
- export declare function createOptimizedAlgorithm<TArgs extends [Graph, ...unknown[]], TResult>(algorithm: (...args: TArgs) => TResult, optionsTransformer?: (graph: Graph, options: unknown) => unknown): (...args: TArgs) => TResult;
42
- //# sourceMappingURL=optimization-helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"optimization-helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/optimization-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAChC;AAaD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAStF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtE,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,CAAC,GAAG,kBAAkB,GAChC,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAO7B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,CAAC,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,OAAO,EACjF,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,EACtC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,GACjE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAW7B"}
@@ -1,59 +0,0 @@
1
- /**
2
- * Check if a graph should use optimizations based on its size
3
- * @param nodeCount - The number of nodes in the graph
4
- * @param edgeCount - The number of edges in the graph
5
- * @returns True if the graph is large enough to benefit from optimizations
6
- */
7
- function shouldUseOptimizations(nodeCount, edgeCount) {
8
- // Use optimizations for graphs with more than 10k nodes or 100k edges
9
- return nodeCount > 10000 || edgeCount > 100000;
10
- }
11
- /**
12
- * Determine if optimizations should be used for a given graph
13
- * @param graph - The graph to check for optimization eligibility
14
- * @param options - Options containing the optimization preference
15
- * @returns True if optimizations should be used for this graph
16
- */
17
- export function shouldOptimize(graph, options = {}) {
18
- const { optimized = "auto" } = options;
19
- if (optimized === "auto") {
20
- // Check graph size
21
- return shouldUseOptimizations(graph.nodeCount, graph.totalEdgeCount);
22
- }
23
- return optimized;
24
- }
25
- /**
26
- * Merge optimization options with algorithm-specific options
27
- * @param graph - The graph to determine optimization settings for
28
- * @param options - Algorithm options that may include optimization settings
29
- * @returns The options with resolved optimization boolean flag
30
- */
31
- export function mergeOptimizationOptions(graph, options) {
32
- const { optimized: userOptimized, ...rest } = options;
33
- return {
34
- ...rest,
35
- optimized: shouldOptimize(graph, userOptimized !== undefined ? { optimized: userOptimized } : {}),
36
- };
37
- }
38
- /**
39
- * Create an optimized version of an algorithm
40
- * @param algorithm - The algorithm function to wrap with optimization support
41
- * @param optionsTransformer - Optional function to transform options before passing to the algorithm
42
- * @returns A wrapped version of the algorithm that applies optimization transformations
43
- * @example
44
- * const optimizedBetweenness = createOptimizedAlgorithm(
45
- * betweennessCentrality,
46
- * (graph, options) => ({...options, optimized: true})
47
- * );
48
- */
49
- export function createOptimizedAlgorithm(algorithm, optionsTransformer) {
50
- return (...args) => {
51
- const [graph, options, ...rest] = args;
52
- if (optionsTransformer && options !== undefined) {
53
- const transformedOptions = optionsTransformer(graph, options);
54
- return algorithm(...[graph, transformedOptions, ...rest]);
55
- }
56
- return algorithm(...args);
57
- };
58
- }
59
- //# sourceMappingURL=optimization-helpers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"optimization-helpers.js","sourceRoot":"","sources":["../../../src/utils/optimization-helpers.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,SAAiB,EAAE,SAAiB;IAChE,sEAAsE;IACtE,OAAO,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG,MAAM,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,UAA8B,EAAE;IACzE,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IAEvC,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACvB,mBAAmB;QACnB,OAAO,sBAAsB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACpC,KAAY,EACZ,OAA+B;IAE/B,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEtD,OAAO;QACH,GAAG,IAAI;QACP,SAAS,EAAE,cAAc,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;AACrC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CACpC,SAAsC,EACtC,kBAAgE;IAEhE,OAAO,CAAC,GAAG,IAAW,EAAW,EAAE;QAC/B,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAEvC,IAAI,kBAAkB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9D,OAAO,SAAS,CAAC,GAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAsB,CAAC,CAAC;QACpF,CAAC;QAED,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;AACN,CAAC"}
@@ -1,2 +0,0 @@
1
- // Algorithm utility functions will be added here
2
- export {};
@@ -1,4 +0,0 @@
1
- export * from "./algorithm-utilities.js";
2
- export * from "./graph-utilities.js";
3
- export * from "./math-utilities.js";
4
- export * from "./matrix-utilities.js";
@@ -1,2 +0,0 @@
1
- // Matrix utility functions will be added here
2
- export {};
@@ -1,87 +0,0 @@
1
- import type { Graph } from "../core/graph.js";
2
-
3
- /**
4
- * Common interface for algorithm options with optimization support
5
- */
6
- export interface OptimizableOptions {
7
- /**
8
- * Whether to use optimized implementations
9
- * - true: Force use of optimizations
10
- * - false: Disable optimizations
11
- * - "auto": Automatically decide based on graph size (default)
12
- */
13
- optimized?: boolean | "auto";
14
- }
15
-
16
- /**
17
- * Check if a graph should use optimizations based on its size
18
- * @param nodeCount - The number of nodes in the graph
19
- * @param edgeCount - The number of edges in the graph
20
- * @returns True if the graph is large enough to benefit from optimizations
21
- */
22
- function shouldUseOptimizations(nodeCount: number, edgeCount: number): boolean {
23
- // Use optimizations for graphs with more than 10k nodes or 100k edges
24
- return nodeCount > 10000 || edgeCount > 100000;
25
- }
26
-
27
- /**
28
- * Determine if optimizations should be used for a given graph
29
- * @param graph - The graph to check for optimization eligibility
30
- * @param options - Options containing the optimization preference
31
- * @returns True if optimizations should be used for this graph
32
- */
33
- export function shouldOptimize(graph: Graph, options: OptimizableOptions = {}): boolean {
34
- const { optimized = "auto" } = options;
35
-
36
- if (optimized === "auto") {
37
- // Check graph size
38
- return shouldUseOptimizations(graph.nodeCount, graph.totalEdgeCount);
39
- }
40
-
41
- return optimized;
42
- }
43
-
44
- /**
45
- * Merge optimization options with algorithm-specific options
46
- * @param graph - The graph to determine optimization settings for
47
- * @param options - Algorithm options that may include optimization settings
48
- * @returns The options with resolved optimization boolean flag
49
- */
50
- export function mergeOptimizationOptions<T extends Record<string, unknown>>(
51
- graph: Graph,
52
- options: T & OptimizableOptions,
53
- ): T & { optimized?: boolean } {
54
- const { optimized: userOptimized, ...rest } = options;
55
-
56
- return {
57
- ...rest,
58
- optimized: shouldOptimize(graph, userOptimized !== undefined ? { optimized: userOptimized } : {}),
59
- } as T & { optimized?: boolean };
60
- }
61
-
62
- /**
63
- * Create an optimized version of an algorithm
64
- * @param algorithm - The algorithm function to wrap with optimization support
65
- * @param optionsTransformer - Optional function to transform options before passing to the algorithm
66
- * @returns A wrapped version of the algorithm that applies optimization transformations
67
- * @example
68
- * const optimizedBetweenness = createOptimizedAlgorithm(
69
- * betweennessCentrality,
70
- * (graph, options) => ({...options, optimized: true})
71
- * );
72
- */
73
- export function createOptimizedAlgorithm<TArgs extends [Graph, ...unknown[]], TResult>(
74
- algorithm: (...args: TArgs) => TResult,
75
- optionsTransformer?: (graph: Graph, options: unknown) => unknown,
76
- ): (...args: TArgs) => TResult {
77
- return (...args: TArgs): TResult => {
78
- const [graph, options, ...rest] = args;
79
-
80
- if (optionsTransformer && options !== undefined) {
81
- const transformedOptions = optionsTransformer(graph, options);
82
- return algorithm(...([graph, transformedOptions, ...rest] as unknown as TArgs));
83
- }
84
-
85
- return algorithm(...args);
86
- };
87
- }