22 * Experiment runner infrastructure
33 */
44
5- import type { Edge , Node } from '../../types/graph' ;
65import { Graph } from '../../graph/graph' ;
76import type { Path } from '../../types/algorithm-results' ;
7+ import type { Edge , Node } from '../../types/graph' ;
88import {
9- spearmanCorrelation ,
10- kendallTau ,
11- } from '../rank-correlation' ;
12- import {
13- ndcg ,
149 meanAveragePrecision ,
1510 meanReciprocalRank ,
11+ ndcg ,
1612 precisionAtK ,
1713 recallAtK ,
1814} from '../ir-metrics' ;
1915import {
20- pairedTTest ,
21- wilcoxonSignedRank ,
22- bootstrapDifferenceTest ,
23- } from '../statistics' ;
24- import {
25- plantGroundTruthPaths ,
2616 addNoisePaths ,
2717 type PlantedPathResult ,
18+ plantGroundTruthPaths ,
2819} from '../path-planting' ;
20+ import {
21+ kendallTau ,
22+ spearmanCorrelation ,
23+ } from '../rank-correlation' ;
24+ import {
25+ bootstrapDifferenceTest ,
26+ pairedTTest ,
27+ wilcoxonSignedRank ,
28+ } from '../statistics' ;
29+ import type { ExperimentReport , MethodComparison , StatisticalTestResult } from '../types' ;
2930import type {
3031 ExperimentConfig ,
31- MetricType ,
3232 MethodConfig ,
33- StatisticalTestType ,
33+ MetricType ,
3434 PathRanker ,
35+ StatisticalTestType ,
3536} from './experiment-config' ;
36- import type { ExperimentReport , MethodComparison , StatisticalTestResult } from '../types' ;
3737
3838/**
3939 * Run a complete evaluation experiment.
@@ -66,10 +66,7 @@ import type { ExperimentReport, MethodComparison, StatisticalTestResult } from '
6666 * console.log(report.winner); // 'MI' (if significantly better)
6767 * ```
6868 */
69- export async function runExperiment < N extends Node , E extends Edge > (
70- config : ExperimentConfig < N , E > ,
71- baseGraph : Graph < N , E >
72- ) : Promise < ExperimentReport > {
69+ export const runExperiment = async < N extends Node , E extends Edge > ( config : ExperimentConfig < N , E > , baseGraph : Graph < N , E > ) : Promise < ExperimentReport > => {
7370 const startTime = Date . now ( ) ;
7471
7572 // Plant ground truth paths
@@ -78,7 +75,7 @@ export async function runExperiment<N extends Node, E extends Edge>(
7875 const relevanceScores = plantedResult . relevanceScores ;
7976
8077 // Add noise paths if configured
81- let graph = plantedResult . graph ;
78+ const graph = plantedResult . graph ;
8279 // Note: Noise paths would be added here if configured
8380 // For now, we'll skip noise to keep experiments simple
8481
@@ -142,7 +139,7 @@ export async function runExperiment<N extends Node, E extends Edge>(
142139 timestamp : new Date ( ) . toISOString ( ) ,
143140 duration : Date . now ( ) - startTime ,
144141 } ;
145- }
142+ } ;
146143
147144/**
148145 * Run cross-validation experiment.
@@ -164,15 +161,11 @@ export async function runExperiment<N extends Node, E extends Edge>(
164161 * console.log(result.stdDev.spearman); // Standard deviation
165162 * ```
166163 */
167- export async function runCrossValidation < N extends Node , E extends Edge > (
168- config : ExperimentConfig < N , E > ,
169- baseGraph : Graph < N , E > ,
170- folds : number = 5
171- ) : Promise < {
164+ export const runCrossValidation = async < N extends Node , E extends Edge > ( config : ExperimentConfig < N , E > , baseGraph : Graph < N , E > , folds : number = 5 ) : Promise < {
172165 foldResults : ExperimentReport [ ] ;
173166 aggregated : ExperimentReport ;
174167 stdDev : ExperimentReport ;
175- } > {
168+ } > => {
176169 const foldResults : ExperimentReport [ ] = [ ] ;
177170
178171 // Run experiment for each fold
@@ -194,17 +187,16 @@ export async function runCrossValidation<N extends Node, E extends Edge>(
194187 const stdDev = calculateStdDev ( foldResults ) ;
195188
196189 return { foldResults, aggregated, stdDev } ;
197- }
190+ } ;
198191
199192/**
200193 * Compute evaluation metrics for a single method run.
194+ * @param rankedPaths
195+ * @param groundTruthPaths
196+ * @param relevanceScores
197+ * @param metricTypes
201198 */
202- function computeMetrics < N extends Node , E extends Edge > (
203- rankedPaths : Array < { path : Path < N , E > ; score : number } > ,
204- groundTruthPaths : Path < N , E > [ ] ,
205- relevanceScores : Map < string , number > ,
206- metricTypes : MetricType [ ]
207- ) : Map < string , number > {
199+ const computeMetrics = < N extends Node , E extends Edge > ( rankedPaths : Array < { path : Path < N , E > ; score : number } > , groundTruthPaths : Path < N , E > [ ] , relevanceScores : Map < string , number > , metricTypes : MetricType [ ] ) : Map < string , number > => {
208200 const metrics = new Map < string , number > ( ) ;
209201
210202 // Extract predicted ranking (path IDs in order)
@@ -272,15 +264,14 @@ function computeMetrics<N extends Node, E extends Edge>(
272264 }
273265
274266 return metrics ;
275- }
267+ } ;
276268
277269/**
278270 * Aggregate metrics across repetitions.
271+ * @param repetitions
272+ * @param metricTypes
279273 */
280- function aggregateMetrics (
281- repetitions : Array < Map < string , number > > ,
282- metricTypes : MetricType [ ]
283- ) : ExperimentReport [ 'methods' ] [ number ] [ 'results' ] {
274+ const aggregateMetrics = ( repetitions : Array < Map < string , number > > , metricTypes : MetricType [ ] ) : ExperimentReport [ 'methods' ] [ number ] [ 'results' ] => {
284275 const aggregated : Record < string , number > = { } ;
285276
286277 // Collect values for each metric
@@ -309,16 +300,15 @@ function aggregateMetrics(
309300 }
310301
311302 return aggregated as ExperimentReport [ 'methods' ] [ number ] [ 'results' ] ;
312- }
303+ } ;
313304
314305/**
315306 * Run statistical tests comparing methods.
307+ * @param methodResults
308+ * @param testTypes
309+ * @param alpha
316310 */
317- function runStatisticalTests (
318- methodResults : Array < { method : string ; repetitions : Array < Map < string , number > > } > ,
319- testTypes : StatisticalTestType [ ] ,
320- alpha : number
321- ) : StatisticalTestResult [ ] {
311+ const runStatisticalTests = ( methodResults : Array < { method : string ; repetitions : Array < Map < string , number > > } > , testTypes : StatisticalTestType [ ] , alpha : number ) : StatisticalTestResult [ ] => {
322312 const tests : StatisticalTestResult [ ] = [ ] ;
323313
324314 // Find best method (by first metric)
@@ -394,28 +384,29 @@ function runStatisticalTests(
394384 }
395385
396386 return tests ;
397- }
387+ } ;
398388
399389/**
400390 * Determine winning method based on primary metric.
391+ * @param methods
392+ * @param primaryMetric
401393 */
402- function determineWinner (
403- methods : MethodComparison [ ] ,
404- primaryMetric : string
405- ) : string {
394+ const determineWinner = ( methods : MethodComparison [ ] , primaryMetric : string ) : string => {
406395 const sorted = [ ...methods ] . sort ( ( a , b ) => {
407396 const scoreA = a . results [ primaryMetric ] ?? 0 ;
408397 const scoreB = b . results [ primaryMetric ] ?? 0 ;
409398 return scoreB - scoreA ;
410399 } ) ;
411400
412401 return sorted [ 0 ] ?. method ?? 'unknown' ;
413- }
402+ } ;
414403
415404/**
416405 * Average metric value across repetitions.
406+ * @param repetitions
407+ * @param metric
417408 */
418- function averageMetric ( repetitions : Array < Map < string , number > > , metric : string ) : number {
409+ const averageMetric = ( repetitions : Array < Map < string , number > > , metric : string ) : number => {
419410 let sum = 0 ;
420411 let count = 0 ;
421412
@@ -428,12 +419,13 @@ function averageMetric(repetitions: Array<Map<string, number>>, metric: string):
428419 }
429420
430421 return count > 0 ? sum / count : 0 ;
431- }
422+ } ;
432423
433424/**
434425 * Aggregate fold results for cross-validation.
426+ * @param folds
435427 */
436- function aggregateFoldResults ( folds : ExperimentReport [ ] ) : ExperimentReport {
428+ const aggregateFoldResults = ( folds : ExperimentReport [ ] ) : ExperimentReport => {
437429 const firstFold = folds [ 0 ] ! ;
438430
439431 // Aggregate methods
@@ -463,12 +455,13 @@ function aggregateFoldResults(folds: ExperimentReport[]): ExperimentReport {
463455 methods : aggregatedMethods ,
464456 statisticalTests : aggregatedTests ,
465457 } ;
466- }
458+ } ;
467459
468460/**
469461 * Calculate standard deviation across folds.
462+ * @param folds
470463 */
471- function calculateStdDev ( folds : ExperimentReport [ ] ) : ExperimentReport {
464+ const calculateStdDev = ( folds : ExperimentReport [ ] ) : ExperimentReport => {
472465 const firstFold = folds [ 0 ] ! ;
473466
474467 // Calculate std dev for each method's metrics
@@ -497,4 +490,4 @@ function calculateStdDev(folds: ExperimentReport[]): ExperimentReport {
497490 methods : methodsWithStdDev ,
498491 statisticalTests : [ ] ,
499492 } ;
500- }
493+ } ;
0 commit comments