@@ -59,6 +59,22 @@ interface FrontierState {
5959/**
6060 * Degree-Prioritised Bidirectional Expansion
6161 *
62+ * **Thesis Alignment**: This is the primary implementation of the seed-bounded
63+ * sampling algorithm described in Chapter 4 of the thesis. It embodies the
64+ * parameter-free design with implicit termination via frontier exhaustion.
65+ *
66+ * **Design Relationship**:
67+ * - BidirectionalBFS: Earlier design, N=2 only, has termination parameters (targetPaths, maxIterations)
68+ * - DegreePrioritisedExpansion: Refined design (this file), N≥1 with identical code path, parameter-free
69+ *
70+ * Use this implementation when:
71+ * - Representative sampling of graph structure is required
72+ * - Evaluation dataset construction demands bias-free samples
73+ * - N≥1 seed nodes need to be supported
74+ * - Termination should be determined by graph structure, not arbitrary limits
75+ *
76+ * For production pathfinding with resource constraints, consider BidirectionalBFS instead.
77+ *
6278 * A unified algorithm for representative graph sampling between N ≥ 1 seed nodes.
6379 * Uses node degree as priority (low degree = high priority) to explore peripheral
6480 * routes before hub-dominated paths.
@@ -94,6 +110,8 @@ interface FrontierState {
94110 * console.log(`Found ${result.paths.length} paths`);
95111 * console.log(`Sampled ${result.sampledNodes.size} nodes`);
96112 * ```
113+ *
114+ * @see BidirectionalBFS - Parameterised version for N=2 with resource constraints
97115 */
98116export class DegreePrioritisedExpansion < T > {
99117 private readonly frontiers : FrontierState [ ] = [ ] ;
@@ -119,8 +137,8 @@ export class DegreePrioritisedExpansion<T> {
119137 // Initialize N frontiers, one per seed
120138 for ( const [ index , seed ] of seeds . entries ( ) ) {
121139 const frontier = new PriorityQueue < string > ( ) ;
122- const degree = expander . getDegree ( seed ) ;
123- frontier . push ( seed , degree ) ;
140+ const priority = expander . calculatePriority ( seed ) ;
141+ frontier . push ( seed , priority ) ;
124142
125143 this . frontiers . push ( {
126144 index : index ,
@@ -180,9 +198,9 @@ export class DegreePrioritisedExpansion<T> {
180198 activeState . visited . add ( targetId ) ;
181199 activeState . parents . set ( targetId , { parent : node , edge : relationshipType } ) ;
182200
183- // Add to frontier with degree as priority
184- const degree = this . expander . getDegree ( targetId ) ;
185- activeState . frontier . push ( targetId , degree ) ;
201+ // Add to frontier with thesis priority as priority
202+ const priority = this . expander . calculatePriority ( targetId ) ;
203+ activeState . frontier . push ( targetId , priority ) ;
186204
187205 // Check intersection with ALL other frontiers (N ≥ 2 only)
188206 // This loop naturally handles all N without branching:
@@ -262,10 +280,9 @@ export class DegreePrioritisedExpansion<T> {
262280 */
263281 private peekPriority ( queue : PriorityQueue < string > ) : number {
264282 // The priority queue is a min-heap, so the front item has minimum priority.
265- // We need to access the heap internals for peek - for now use getDegree on first item.
266- // This is safe because items are added with their degree as priority.
283+ // We use calculatePriority to ensure consistent prioritization across the algorithm.
267284 for ( const item of queue ) {
268- return this . expander . getDegree ( item ) ;
285+ return this . expander . calculatePriority ( item ) ;
269286 }
270287 return Infinity ;
271288 }
0 commit comments