Skip to content

Commit 675d198

Browse files
committed
fix(algorithms): fix Nx daemon circular dependency and increase memory
Fix root cause of Nx daemon hanging during pre-commit hooks: - Remove circular dependency: typecheck no longer depends on ^build (build → typecheck → ^build was causing deadlock) - Increase daemon memory limit from 512MB to 2048MB - Disable Nx daemon in lint-staged (NX_DAEMON=false) - Fix non-null assertions in rank-correlation.ts Resolves issue where 'nx affected --target=lint:fix|typecheck' hung indefinitely. Related commits: - Phase 8: b425e6e (evaluation metrics) - Phase 9: 18895fb (baseline rankers)
1 parent 18895fb commit 675d198

File tree

9 files changed

+68
-96
lines changed

9 files changed

+68
-96
lines changed

.lintstagedrc.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ export default {
1111

1212
// TypeScript and JavaScript files in packages and apps
1313
'{packages,apps}/**/*.{ts,tsx,js,jsx}': [
14-
// Run cached lint:fix for affected projects using Nx
15-
'nx affected --target=lint:fix'
14+
// Run cached lint:fix for affected projects using Nx (no daemon for pre-commit)
15+
() => 'NX_DAEMON=false nx affected --target=lint:fix'
1616
],
1717

18-
// Type check all affected projects
18+
// Type check all affected projects (no daemon for pre-commit)
1919
'*.{ts,tsx}': [
20-
() => 'nx affected --target=typecheck'
20+
() => 'NX_DAEMON=false nx affected --target=typecheck'
2121
],
2222

2323
// GitHub workflow files (actionlint only validates workflow files in .github/workflows/)

nx.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"heartbeatIntervalMs": 60000,
1717
"processExitTimeoutMs": 15000,
1818
"cleanupOnProcessExit": true,
19-
"maxMemoryUsage": "512MB"
19+
"maxMemoryUsage": "2048MB"
2020
}
2121
},
2222
"workspaceLayout": {
@@ -371,9 +371,6 @@
371371
"command": "tsc --noEmit",
372372
"cwd": "{projectRoot}"
373373
},
374-
"dependsOn": [
375-
"^build"
376-
],
377374
"inputs": [
378375
"source",
379376
"configs",

packages/algorithms/src/evaluation/baselines/degree-ranker.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
import type { Graph } from '../../graph/graph';
6-
import type { Edge, Node } from '../../types/graph';
7-
import type { Path } from '../../types/algorithm-results';
86
import type { RankedPath } from '../../pathfinding/path-ranking';
7+
import type { Path } from '../../types/algorithm-results';
8+
import type { Edge, Node } from '../../types/graph';
99

1010
/**
1111
* Rank paths by sum of node degrees along path.
@@ -15,10 +15,7 @@ import type { RankedPath } from '../../pathfinding/path-ranking';
1515
* @param paths - Paths to rank
1616
* @returns Paths sorted by total degree (descending)
1717
*/
18-
export function degreeBasedRanker<N extends Node, E extends Edge>(
19-
graph: Graph<N, E>,
20-
paths: Path<N, E>[]
21-
): RankedPath<N, E>[] {
18+
export const degreeBasedRanker = <N extends Node, E extends Edge>(graph: Graph<N, E>, paths: Path<N, E>[]): RankedPath<N, E>[] => {
2219
// Calculate total degree for each path
2320
const pathScores = paths.map((path) => {
2421
let totalDegree = 0;
@@ -44,4 +41,4 @@ export function degreeBasedRanker<N extends Node, E extends Edge>(
4441
pathScores.sort((a, b) => b.score - a.score);
4542

4643
return pathScores;
47-
}
44+
};

packages/algorithms/src/evaluation/baselines/pagerank-ranker.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
import type { Graph } from '../../graph/graph';
6-
import type { Edge, Node } from '../../types/graph';
7-
import type { Path } from '../../types/algorithm-results';
86
import type { RankedPath } from '../../pathfinding/path-ranking';
7+
import type { Path } from '../../types/algorithm-results';
8+
import type { Edge, Node } from '../../types/graph';
99

1010
/**
1111
* Compute PageRank scores for all nodes in the graph.
@@ -19,12 +19,7 @@ import type { RankedPath } from '../../pathfinding/path-ranking';
1919
* @param tolerance - Convergence tolerance (default: 1e-6)
2020
* @returns Map of node ID to PageRank score
2121
*/
22-
function computePageRank<N extends Node, E extends Edge>(
23-
graph: Graph<N, E>,
24-
dampingFactor: number = 0.85,
25-
maxIterations: number = 100,
26-
tolerance: number = 1e-6
27-
): Map<string, number> {
22+
const computePageRank = <N extends Node, E extends Edge>(graph: Graph<N, E>, dampingFactor: number = 0.85, maxIterations: number = 100, tolerance: number = 1e-6): Map<string, number> => {
2823
const nodes = graph.getAllNodes();
2924
const n = nodes.length;
3025

@@ -98,7 +93,7 @@ function computePageRank<N extends Node, E extends Edge>(
9893
}
9994

10095
return pageRank;
101-
}
96+
};
10297

10398
/**
10499
* Rank paths by sum of PageRank scores along path.
@@ -109,11 +104,7 @@ function computePageRank<N extends Node, E extends Edge>(
109104
* @param dampingFactor - PageRank damping (default: 0.85)
110105
* @returns Paths sorted by total PageRank (descending)
111106
*/
112-
export function pageRankRanker<N extends Node, E extends Edge>(
113-
graph: Graph<N, E>,
114-
paths: Path<N, E>[],
115-
dampingFactor?: number
116-
): RankedPath<N, E>[] {
107+
export const pageRankRanker = <N extends Node, E extends Edge>(graph: Graph<N, E>, paths: Path<N, E>[], dampingFactor?: number): RankedPath<N, E>[] => {
117108
// Compute PageRank for all nodes
118109
const pageRank = computePageRank(graph, dampingFactor);
119110

@@ -141,4 +132,4 @@ export function pageRankRanker<N extends Node, E extends Edge>(
141132
pathScores.sort((a, b) => b.score - a.score);
142133

143134
return pathScores;
144-
}
135+
};

packages/algorithms/src/evaluation/baselines/random-ranker.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
* Random path ranking baseline
33
*/
44

5-
import type { Edge, Node } from '../../types/graph';
6-
import type { Path } from '../../types/algorithm-results';
75
import type { RankedPath } from '../../pathfinding/path-ranking';
6+
import type { Path } from '../../types/algorithm-results';
7+
import type { Edge, Node } from '../../types/graph';
88

99
/**
1010
* Seeded random number generator for reproducibility.
@@ -26,6 +26,7 @@ class SeededRandom {
2626

2727
/**
2828
* Shuffle array using Fisher-Yates algorithm with seeded random.
29+
* @param array
2930
*/
3031
shuffle<T>(array: T[]): T[] {
3132
const result = [...array];
@@ -45,10 +46,7 @@ class SeededRandom {
4546
* @param seed - Random seed for reproducibility
4647
* @returns Randomly ordered paths with scores
4748
*/
48-
export function randomRanker<N extends Node, E extends Edge>(
49-
paths: Path<N, E>[],
50-
seed?: number
51-
): RankedPath<N, E>[] {
49+
export const randomRanker = <N extends Node, E extends Edge>(paths: Path<N, E>[], seed?: number): RankedPath<N, E>[] => {
5250
const rng = new SeededRandom(seed ?? Date.now());
5351

5452
// Shuffle paths randomly
@@ -61,4 +59,4 @@ export function randomRanker<N extends Node, E extends Edge>(
6159
geometricMeanMI: 0, // No MI computation for random baseline
6260
edgeMIValues: [],
6361
}));
64-
}
62+
};

packages/algorithms/src/evaluation/baselines/shortest-path-ranker.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
* Shortest path ranking baseline
33
*/
44

5-
import type { Edge, Node } from '../../types/graph';
6-
import type { Path } from '../../types/algorithm-results';
75
import type { RankedPath } from '../../pathfinding/path-ranking';
6+
import type { Path } from '../../types/algorithm-results';
7+
import type { Edge, Node } from '../../types/graph';
88

99
/**
1010
* Rank paths by length (shortest first).
@@ -13,9 +13,7 @@ import type { RankedPath } from '../../pathfinding/path-ranking';
1313
* @param paths - Paths to rank
1414
* @returns Paths sorted by length (ascending)
1515
*/
16-
export function shortestPathRanker<N extends Node, E extends Edge>(
17-
paths: Path<N, E>[]
18-
): RankedPath<N, E>[] {
16+
export const shortestPathRanker = <N extends Node, E extends Edge>(paths: Path<N, E>[]): RankedPath<N, E>[] => {
1917
// Calculate scores (inverse of length so shorter paths have higher scores)
2018
const pathScores = paths.map((path) => {
2119
const length = path.edges.length;
@@ -36,4 +34,4 @@ export function shortestPathRanker<N extends Node, E extends Edge>(
3634
pathScores.sort((a, b) => b.score - a.score);
3735

3836
return pathScores;
39-
}
37+
};

packages/algorithms/src/evaluation/baselines/weight-ranker.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
* Weight-based path ranking baseline
33
*/
44

5-
import type { Edge, Node } from '../../types/graph';
6-
import type { Path } from '../../types/algorithm-results';
75
import type { RankedPath } from '../../pathfinding/path-ranking';
6+
import type { Path } from '../../types/algorithm-results';
7+
import type { Edge, Node } from '../../types/graph';
88

99
/**
1010
* Rank paths by sum of edge weights.
@@ -14,10 +14,7 @@ import type { RankedPath } from '../../pathfinding/path-ranking';
1414
* @param weightFn - Function to extract weight from edge
1515
* @returns Paths sorted by total weight (descending)
1616
*/
17-
export function weightBasedRanker<N extends Node, E extends Edge>(
18-
paths: Path<N, E>[],
19-
weightFn: (edge: E) => number
20-
): RankedPath<N, E>[] {
17+
export const weightBasedRanker = <N extends Node, E extends Edge>(paths: Path<N, E>[], weightFn: (edge: E) => number): RankedPath<N, E>[] => {
2118
// Calculate total weight for each path
2219
const pathScores = paths.map((path) => {
2320
let totalWeight = 0;
@@ -42,4 +39,4 @@ export function weightBasedRanker<N extends Node, E extends Edge>(
4239
pathScores.sort((a, b) => b.score - a.score);
4340

4441
return pathScores;
45-
}
42+
};

packages/algorithms/src/evaluation/ir-metrics.ts

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ interface ItemWithRelevance {
1616
* @param k - Cutoff position
1717
* @returns DCG@k score
1818
*/
19-
function dcgAtK(items: ItemWithRelevance[], k: number): number {
19+
const dcgAtK = (items: ItemWithRelevance[], k: number): number => {
2020
const discounted = items.slice(0, k);
2121
let sum = 0;
2222

@@ -30,7 +30,7 @@ function dcgAtK(items: ItemWithRelevance[], k: number): number {
3030
}
3131

3232
return sum;
33-
}
33+
};
3434

3535
/**
3636
* Normalized Discounted Cumulative Gain.
@@ -41,11 +41,7 @@ function dcgAtK(items: ItemWithRelevance[], k: number): number {
4141
* @param k - Cutoff position (default: all items)
4242
* @returns NDCG@k ∈ [0, 1], where 1 = perfect ranking
4343
*/
44-
export function ndcg(
45-
predicted: Array<{ id: string; relevance: number }>,
46-
groundTruth: Array<{ id: string; relevance: number }>,
47-
k?: number
48-
): number {
44+
export const ndcg = (predicted: Array<{ id: string; relevance: number }>, groundTruth: Array<{ id: string; relevance: number }>, k?: number): number => {
4945
if (predicted.length === 0 || groundTruth.length === 0) {
5046
return 0;
5147
}
@@ -59,7 +55,7 @@ export function ndcg(
5955
}
6056

6157
return predictedDCG / idealDCG;
62-
}
58+
};
6359

6460
/**
6561
* Mean Average Precision.
@@ -69,10 +65,7 @@ export function ndcg(
6965
* @param relevantItems - Set of relevant item IDs
7066
* @returns MAP ∈ [0, 1]
7167
*/
72-
export function meanAveragePrecision(
73-
predicted: string[],
74-
relevantItems: Set<string>
75-
): number {
68+
export const meanAveragePrecision = (predicted: string[], relevantItems: Set<string>): number => {
7669
if (predicted.length === 0 || relevantItems.size === 0) {
7770
return 0;
7871
}
@@ -95,7 +88,7 @@ export function meanAveragePrecision(
9588
}
9689

9790
return precisionSum / relevantCount;
98-
}
91+
};
9992

10093
/**
10194
* Mean Reciprocal Rank.
@@ -105,10 +98,7 @@ export function meanAveragePrecision(
10598
* @param relevantItems - Set of relevant item IDs
10699
* @returns MRR ∈ [0, 1]
107100
*/
108-
export function meanReciprocalRank(
109-
predicted: string[],
110-
relevantItems: Set<string>
111-
): number {
101+
export const meanReciprocalRank = (predicted: string[], relevantItems: Set<string>): number => {
112102
if (predicted.length === 0 || relevantItems.size === 0) {
113103
return 0;
114104
}
@@ -122,7 +112,7 @@ export function meanReciprocalRank(
122112
}
123113

124114
return 0; // No relevant items found
125-
}
115+
};
126116

127117
/**
128118
* Precision at K.
@@ -133,11 +123,7 @@ export function meanReciprocalRank(
133123
* @param k - Cutoff position
134124
* @returns P@K ∈ [0, 1]
135125
*/
136-
export function precisionAtK(
137-
predicted: string[],
138-
relevantItems: Set<string>,
139-
k: number
140-
): number {
126+
export const precisionAtK = (predicted: string[], relevantItems: Set<string>, k: number): number => {
141127
if (predicted.length === 0 || relevantItems.size === 0 || k <= 0) {
142128
return 0;
143129
}
@@ -146,7 +132,7 @@ export function precisionAtK(
146132
const relevantInTopK = topK.filter(item => relevantItems.has(item)).length;
147133

148134
return relevantInTopK / k;
149-
}
135+
};
150136

151137
/**
152138
* Recall at K.
@@ -157,11 +143,7 @@ export function precisionAtK(
157143
* @param k - Cutoff position
158144
* @returns R@K ∈ [0, 1]
159145
*/
160-
export function recallAtK(
161-
predicted: string[],
162-
relevantItems: Set<string>,
163-
k: number
164-
): number {
146+
export const recallAtK = (predicted: string[], relevantItems: Set<string>, k: number): number => {
165147
if (predicted.length === 0 || relevantItems.size === 0 || k <= 0) {
166148
return 0;
167149
}
@@ -170,4 +152,4 @@ export function recallAtK(
170152
const relevantInTopK = topK.filter(item => relevantItems.has(item)).length;
171153

172154
return relevantInTopK / relevantItems.size;
173-
}
155+
};

0 commit comments

Comments
 (0)