@@ -17,9 +17,12 @@ import { BidirectionalBFS } from "../algorithms/traversal/bidirectional-bfs.js";
1717import type { DegreePrioritisedExpansionResult } from "../algorithms/traversal/degree-prioritised-expansion.js" ;
1818import { DegreePrioritisedExpansion } from "../algorithms/traversal/degree-prioritised-expansion.js" ;
1919import type { OverlapBasedExpansionResult } from "../algorithms/traversal/overlap-based/overlap-result.js" ;
20+ import { computeNodeSalienceFromRankedPaths , SaliencePrioritisedExpansion } from "../algorithms/traversal/salience-prioritised-expansion.js" ;
2021import { FrontierBalancedExpansion } from "../experiments/baselines/frontier-balanced.js" ;
22+ import { registerOverlapSuts } from "./register-overlap-suts.js" ;
2123// Re-export overlap-based SUT registration for convenience
22- export { OVERLAP_SUT_REGISTRATIONS , overlapSutRegistry , registerOverlapSuts } from "./register-overlap-suts.js" ;
24+ export { OVERLAP_SUT_REGISTRATIONS , overlapSutRegistry , registerOverlapSuts } from "./register-overlap-suts.js" ;
25+ import { rankPaths } from "../algorithms/pathfinding/path-ranking.js" ;
2326import { RandomPriorityExpansion } from "../experiments/baselines/random-priority.js" ;
2427import { StandardBfsExpansion } from "../experiments/baselines/standard-bfs.js" ;
2528import type { GraphExpander } from "../interfaces/graph-expander.js" ;
@@ -36,6 +39,9 @@ export interface ExpansionInputs {
3639
3740 /** Seed node IDs for expansion */
3841 seeds : string [ ] ;
42+
43+ /** Optional underlying graph for algorithms that need full graph access (e.g., path ranking) */
44+ graph ?: import ( "../algorithms/graph/graph.js" ) . Graph < import ( "../algorithms/types/graph.js" ) . Node , import ( "../algorithms/types/graph.js" ) . Edge > ;
3945}
4046
4147/**
@@ -106,6 +112,15 @@ export const SUT_REGISTRATIONS: Record<string, SutRegistration> = {
106112 tags : [ "traversal" , "bidirectional" , "baseline" , "null-hypothesis" ] ,
107113 description : "Bidirectional expansion with random node selection" ,
108114 } ,
115+ "salience-prioritised-v1.0.0" : {
116+ id : "salience-prioritised-v1.0.0" ,
117+ name : "Salience-Prioritised Expansion" ,
118+ version : "1.0.0" ,
119+ role : "baseline" ,
120+ config : { } satisfies { topK ?: number } ,
121+ tags : [ "traversal" , "bidirectional" , "salience-aware" , "parameter-free" ] ,
122+ description : "Path quality-aware expansion prioritizing nodes by participation in high-salience paths" ,
123+ } ,
109124} ;
110125
111126/**
@@ -246,6 +261,80 @@ class RandomPrioritySUT implements SUT<ExpansionInputs, ExpansionResult> {
246261 }
247262}
248263
264+ /**
265+ * SUT wrapper for Salience-Prioritised Expansion.
266+ *
267+ * **Novel Contribution**: Pre-computes node salience scores from Path Salience ranking
268+ * and uses them to prioritize expansion toward high-quality paths.
269+ *
270+ * This SUT automatically:
271+ * 1. Runs Path Salience ranking on the graph to find top-K salient paths
272+ * 2. Computes node participation scores for those paths
273+ * 3. Uses those scores to drive expansion (higher salience = expanded earlier)
274+ *
275+ * **Config**:
276+ * - topK: Number of top salient paths to use for scoring (default: 10)
277+ *
278+ * **Expected Outcome**: Higher salience coverage than degree-prioritised expansion
279+ * because the expansion naturally gravitates toward nodes that appear in
280+ * high-quality paths.
281+ */
282+ class SaliencePrioritisedSUT implements SUT < ExpansionInputs , ExpansionResult > {
283+ readonly id = "salience-prioritised-v1.0.0" ;
284+ readonly config : Readonly < Record < string , unknown > > ;
285+
286+ constructor ( config ?: Record < string , unknown > ) {
287+ this . config = { ...config } ;
288+ }
289+
290+ async run ( inputs : ExpansionInputs ) : Promise < ExpansionResult > {
291+ const { expander, seeds, graph } = inputs ;
292+ const topK = typeof this . config ?. topK === "number" ? this . config . topK : 10 ;
293+
294+ // Get the graph for path ranking
295+ // Priority: 1) Use provided graph, 2) Call toGraph() if available, 3) Error
296+ let graphForRanking : import ( "../algorithms/graph/graph.js" ) . Graph < import ( "../algorithms/types/graph.js" ) . Node , import ( "../algorithms/types/graph.js" ) . Edge > ;
297+ if ( graph ) {
298+ graphForRanking = graph ;
299+ } else if ( "toGraph" in expander && typeof expander . toGraph === "function" ) {
300+ graphForRanking = await ( expander as unknown as { toGraph : ( ) => Promise < typeof graphForRanking > } ) . toGraph ( ) ;
301+ } else {
302+ throw new Error ( "SaliencePrioritisedSUT requires either inputs.graph or expander.toGraph()" ) ;
303+ }
304+
305+ // Pre-compute salience scores by running Path Salience ranking
306+ const nodeSalience = new Map < string , number > ( ) ;
307+
308+ // Run Path Salience for each seed pair to collect top-K paths
309+ for ( let index = 0 ; index < seeds . length ; index ++ ) {
310+ for ( let index_ = index + 1 ; index_ < seeds . length ; index_ ++ ) {
311+ const result = rankPaths ( graphForRanking , seeds [ index ] , seeds [ index_ ] , {
312+ lambda : 0 ,
313+ maxPaths : topK * 2 , // Get more than needed
314+ shortestOnly : false ,
315+ traversalMode : "undirected" ,
316+ } ) ;
317+
318+ if ( result . ok && result . value . some ) {
319+ const ranked = result . value . value ;
320+ // Compute node salience from top-K paths
321+ const topKPaths = ranked . slice ( 0 , topK ) ;
322+ const scores = computeNodeSalienceFromRankedPaths ( topKPaths ) ;
323+
324+ // Merge scores (sum across all pairs)
325+ for ( const [ node , score ] of scores ) {
326+ nodeSalience . set ( node , ( nodeSalience . get ( node ) ?? 0 ) + score ) ;
327+ }
328+ }
329+ }
330+ }
331+
332+ // Create and run salience-prioritised expansion
333+ const algorithm = new SaliencePrioritisedExpansion ( expander , seeds , nodeSalience ) ;
334+ return algorithm . run ( ) ;
335+ }
336+ }
337+
249338/**
250339 * Register all expansion SUTs with a registry.
251340 *
@@ -285,6 +374,15 @@ export const registerExpansionSuts = (
285374 ( config ?: Record < string , unknown > ) : SUT < ExpansionInputs , ExpansionResult > => new RandomPrioritySUT ( config )
286375 ) ;
287376
377+ // Salience-Prioritised (Baseline - path quality-aware expansion)
378+ registry . register (
379+ SUT_REGISTRATIONS [ "salience-prioritised-v1.0.0" ] ,
380+ ( config ?: Record < string , unknown > ) : SUT < ExpansionInputs , ExpansionResult > => new SaliencePrioritisedSUT ( config )
381+ ) ;
382+
383+ // Register all 27 overlap-based expansion variants
384+ registerOverlapSuts ( registry ) ;
385+
288386 return registry ;
289387} ;
290388
0 commit comments