@@ -5,7 +5,6 @@ interface QueueNode {
55 index : number ;
66 cost : number ;
77 path : ConvertPathNode [ ] ;
8- visitedBorder : number ;
98} ;
109interface CategoryChangeCost {
1110 from : string ;
@@ -19,7 +18,6 @@ interface CategoryAdaptiveCost {
1918 cost : number ; // Cost to apply when a conversion involves all of the specified categories in sequence.
2019}
2120
22-
2321// Parameters for pathfinding algorithm.
2422const DEPTH_COST : number = 1 ; // Base cost for each conversion step. Higher values will make the algorithm prefer shorter paths more strongly.
2523const DEFAULT_CATEGORY_CHANGE_COST : number = 0.6 ; // Default cost for category changes not specified in CATEGORY_CHANGE_COSTS
@@ -333,30 +331,35 @@ export class TraversionGraph {
333331
334332 public async * searchPath ( from : ConvertPathNode , to : ConvertPathNode , simpleMode : boolean ) : AsyncGenerator < ConvertPathNode [ ] > {
335333 // Dijkstra's algorithm
336- // Priority queue of {index, cost, path}
337334 let queue : PriorityQueue < QueueNode > = new PriorityQueue < QueueNode > (
338335 1000 ,
339336 ( a : QueueNode , b : QueueNode ) => a . cost - b . cost
340337 ) ;
341- let visited = new Array < number > ( ) ;
338+
339+ let minCosts = new Map < number , number > ( ) ;
340+
342341 const fromIdentifier = from . format . mime + `(${ from . format . format } )` ;
343342 const toIdentifier = to . format . mime + `(${ to . format . format } )` ;
344343 let fromIndex = this . nodes . findIndex ( node => node . identifier === fromIdentifier ) ;
345344 let toIndex = this . nodes . findIndex ( node => node . identifier === toIdentifier ) ;
346345 if ( fromIndex === - 1 || toIndex === - 1 ) return [ ] ; // If either format is not in the graph, return empty array
347- queue . add ( { index : fromIndex , cost : 0 , path : [ from ] , visitedBorder : visited . length } ) ;
346+
347+ queue . add ( { index : fromIndex , cost : 0 , path : [ from ] } ) ;
348+ minCosts . set ( fromIndex , 0 ) ;
349+
348350 console . log ( `Starting path search from ${ from . format . mime } (${ from . handler ?. name } ) to ${ to . format . mime } (${ to . handler ?. name } ) (simple mode: ${ simpleMode } )` ) ;
349351 let iterations = 0 ;
350352 let pathsFound = 0 ;
353+
351354 while ( queue . size ( ) > 0 ) {
352355 iterations ++ ;
353- // Get the node with the lowest cost
354356 let current = queue . poll ( ) ! ;
355- const indexInVisited = visited . indexOf ( current . index ) ;
356- if ( indexInVisited >= 0 && indexInVisited < current . visitedBorder ) {
357+
358+ if ( current . index !== toIndex && current . cost > ( minCosts . get ( current . index ) ?? Infinity ) ) {
357359 this . dispatchEvent ( "skipped" , current . path ) ;
358360 continue ;
359361 }
362+
360363 if ( current . index === toIndex ) {
361364 // Return the path of handlers and formats to get from the input format to the output format
362365 const logString = `${ iterations } with cost ${ current . cost . toFixed ( 3 ) } : ${ current . path . map ( p => p . handler . name + "(" + p . format . mime + ")" ) . join ( " → " ) } ` ;
@@ -373,21 +376,26 @@ export class TraversionGraph {
373376 }
374377 continue ;
375378 }
376- visited . push ( current . index ) ;
379+
377380 this . dispatchEvent ( "searching" , current . path ) ;
378381 this . nodes [ current . index ] . edges . forEach ( edgeIndex => {
379382 let edge = this . edges [ edgeIndex ] ;
380- const indexInVisited = visited . indexOf ( edge . to . index ) ;
381- if ( indexInVisited >= 0 && indexInVisited < current . visitedBorder ) return ;
383+
382384 const handler = this . handlers . find ( h => h . name === edge . handler ) ;
383385 if ( ! handler ) return ; // If the handler for this edge is not found, skip it
384386
385387 let path = current . path . concat ( { handler : handler , format : edge . to . format } ) ;
388+ let newCost = current . cost + edge . cost + this . calculateAdaptiveCost ( path ) ;
389+
390+ if ( edge . to . index !== toIndex ) {
391+ if ( newCost >= ( minCosts . get ( edge . to . index ) ?? Infinity ) ) return ;
392+ minCosts . set ( edge . to . index , newCost ) ;
393+ }
394+
386395 queue . add ( {
387396 index : edge . to . index ,
388- cost : current . cost + edge . cost + this . calculateAdaptiveCost ( path ) ,
389- path : path ,
390- visitedBorder : visited . length
397+ cost : newCost ,
398+ path : path
391399 } ) ;
392400 } ) ;
393401 if ( iterations % LOG_FREQUENCY === 0 ) {
0 commit comments