@@ -12,6 +12,7 @@ use lib_tsalign::a_star_aligner::{
1212 template_switch_distance:: { EqualCostRange , TemplateSwitchDirection } ,
1313} ;
1414use log:: { debug, trace} ;
15+ use num_traits:: Zero ;
1516use std:: {
1617 fmt:: Write ,
1718 iter,
@@ -34,11 +35,19 @@ use crate::{
3435
3536mod chainer;
3637
38+ pub struct AlignmentParameters {
39+ /// The step width for generating successors during chaining.
40+ ///
41+ /// At most `max_successors` will be generated at a time, but at least all with minimum chaining cost.
42+ pub max_successors : usize ,
43+ }
44+
3745#[ expect( clippy:: too_many_arguments) ]
3846pub fn align < AlphabetType : Alphabet , Cost : AStarCost > (
3947 sequences : & AlignmentSequences ,
4048 start : AlignmentCoordinates ,
4149 end : AlignmentCoordinates ,
50+ parameters : & AlignmentParameters ,
4251 alignment_costs : & AlignmentCosts < Cost > ,
4352 rc_fn : & dyn Fn ( u8 ) -> u8 ,
4453 max_match_run : u32 ,
@@ -58,6 +67,7 @@ pub fn align<AlphabetType: Alphabet, Cost: AStarCost>(
5867 chaining_cost_function,
5968 & alignment_costs. ts_limits ,
6069 k,
70+ parameters. max_successors ,
6171 ) ;
6272 let mut astar = AStar :: new ( context) ;
6373 let mut chaining_execution_count = 0 ;
@@ -104,21 +114,55 @@ pub fn align<AlphabetType: Alphabet, Cost: AStarCost>(
104114 }
105115 match identifier {
106116 Identifier :: Start => write!( s, "start" ) . unwrap( ) ,
107- Identifier :: Primary { index } => {
108- write!( s, "P{}" , anchors. primary( * index) ) . unwrap( )
117+ Identifier :: StartToPrimary { offset } => {
118+ write!( s, "start-to-primary-{offset}" ) . unwrap( )
119+ }
120+ Identifier :: StartToSecondary { ts_kind, offset } => {
121+ write!( s, "start-to-secondary{}-{offset}" , ts_kind. digits( ) )
122+ . unwrap( )
109123 }
110- Identifier :: Secondary {
124+ Identifier :: PrimaryToPrimary { index, offset } => {
125+ write!( s, "P{}-to-primary-{offset}" , anchors. primary( * index) )
126+ . unwrap( )
127+ }
128+ Identifier :: PrimaryToSecondary {
129+ index,
130+ ts_kind,
131+ offset,
132+ } => write!(
133+ s,
134+ "P{}-to-secondary{}-{offset}" ,
135+ anchors. primary( * index) ,
136+ ts_kind. digits( )
137+ )
138+ . unwrap( ) ,
139+ Identifier :: SecondaryToSecondary {
111140 index,
112141 ts_kind,
113142 first_secondary_index,
143+ offset,
114144 } => write!(
115145 s,
116- "S{}{}->{}" ,
146+ "S{}{}->{}-to-secondary-{offset} " ,
117147 ts_kind. digits( ) ,
118148 anchors. secondary( * first_secondary_index, * ts_kind) ,
119149 anchors. secondary( * index, * ts_kind) ,
120150 )
121151 . unwrap( ) ,
152+ Identifier :: SecondaryToPrimary {
153+ index,
154+ ts_kind,
155+ first_secondary_index,
156+ offset,
157+ } => write!(
158+ s,
159+ "S{}{}->{}-to-primary-{offset}" ,
160+ ts_kind. digits( ) ,
161+ anchors. secondary( * first_secondary_index, * ts_kind) ,
162+ anchors. secondary( * index, * ts_kind) ,
163+ )
164+ . unwrap( ) ,
165+
122166 Identifier :: End => write!( s, "end" ) . unwrap( ) ,
123167 }
124168 }
@@ -305,9 +349,29 @@ fn evaluate_chain<Cost: AStarCost>(
305349 let k = usize:: try_from ( max_match_run + 1 ) . unwrap ( ) ;
306350 let mut current_upper_bound = Cost :: zero ( ) ;
307351 let mut alignments = Vec :: new ( ) ;
308- for window in chain. windows ( 2 ) {
309- let from_anchor = window[ 0 ] ;
310- let to_anchor = window[ 1 ] ;
352+ let mut current_from_index = 0 ;
353+
354+ loop {
355+ let from_anchor = chain[ current_from_index] ;
356+ let Some ( ( to_anchor_index, to_anchor) ) = chain
357+ . iter ( )
358+ . copied ( )
359+ . enumerate ( )
360+ . skip ( current_from_index + 1 )
361+ . find ( |( _, identifier) | match identifier {
362+ Identifier :: Start => true ,
363+ Identifier :: StartToPrimary { .. } => false ,
364+ Identifier :: StartToSecondary { .. } => false ,
365+ Identifier :: PrimaryToPrimary { offset, .. }
366+ | Identifier :: PrimaryToSecondary { offset, .. }
367+ | Identifier :: SecondaryToSecondary { offset, .. }
368+ | Identifier :: SecondaryToPrimary { offset, .. } => offset. is_zero ( ) ,
369+ Identifier :: End => true ,
370+ } )
371+ else {
372+ break ;
373+ } ;
374+ current_from_index = to_anchor_index;
311375
312376 match ( from_anchor, to_anchor) {
313377 ( Identifier :: Start , Identifier :: End ) => {
@@ -328,7 +392,11 @@ fn evaluate_chain<Cost: AStarCost>(
328392 }
329393 current_upper_bound += chaining_cost_function. start_to_end ( ) ;
330394 }
331- ( Identifier :: Start , Identifier :: Primary { index } ) => {
395+ (
396+ Identifier :: Start ,
397+ Identifier :: PrimaryToPrimary { index, .. }
398+ | Identifier :: PrimaryToSecondary { index, .. } ,
399+ ) => {
332400 let end = anchors. primary ( index) . start ( ) ;
333401 if final_evaluation || !chaining_cost_function. is_primary_from_start_exact ( index) {
334402 let alignment = GapAffineAlignment :: new (
@@ -355,7 +423,11 @@ fn evaluate_chain<Cost: AStarCost>(
355423 }
356424 current_upper_bound += chaining_cost_function. primary_from_start ( index) ;
357425 }
358- ( Identifier :: Start , Identifier :: Secondary { index, ts_kind, .. } ) => {
426+ (
427+ Identifier :: Start ,
428+ Identifier :: SecondaryToPrimary { index, ts_kind, .. }
429+ | Identifier :: SecondaryToSecondary { index, ts_kind, .. } ,
430+ ) => {
359431 let end = anchors. secondary ( index, ts_kind) . start ( ts_kind) ;
360432 if final_evaluation
361433 || !chaining_cost_function. is_jump_12_from_start_exact ( index, ts_kind)
@@ -386,7 +458,7 @@ fn evaluate_chain<Cost: AStarCost>(
386458 }
387459 current_upper_bound += chaining_cost_function. jump_12_from_start ( index, ts_kind) ;
388460 }
389- ( Identifier :: Primary { index } , Identifier :: End ) => {
461+ ( Identifier :: PrimaryToPrimary { index, .. } , Identifier :: End ) => {
390462 let start = anchors. primary ( index) . end ( k) ;
391463 if final_evaluation || !chaining_cost_function. is_primary_to_end_exact ( index) {
392464 let alignment = GapAffineAlignment :: new (
@@ -410,7 +482,7 @@ fn evaluate_chain<Cost: AStarCost>(
410482 }
411483 current_upper_bound += chaining_cost_function. primary_to_end ( index) ;
412484 }
413- ( Identifier :: Secondary { index, ts_kind, .. } , Identifier :: End ) => {
485+ ( Identifier :: SecondaryToPrimary { index, ts_kind, .. } , Identifier :: End ) => {
414486 let start = anchors. secondary ( index, ts_kind) . end ( ts_kind, k) ;
415487 if final_evaluation
416488 || !chaining_cost_function. is_jump_34_to_end_exact ( index, ts_kind)
@@ -443,8 +515,15 @@ fn evaluate_chain<Cost: AStarCost>(
443515 current_upper_bound += chaining_cost_function. jump_34_to_end ( index, ts_kind) ;
444516 }
445517 (
446- Identifier :: Primary { index : from_index } ,
447- Identifier :: Primary { index : to_index } ,
518+ Identifier :: PrimaryToPrimary {
519+ index : from_index, ..
520+ } ,
521+ Identifier :: PrimaryToPrimary {
522+ index : to_index, ..
523+ }
524+ | Identifier :: PrimaryToSecondary {
525+ index : to_index, ..
526+ } ,
448527 ) => {
449528 if anchors
450529 . primary ( from_index)
@@ -487,8 +566,15 @@ fn evaluate_chain<Cost: AStarCost>(
487566 current_upper_bound += chaining_cost_function. primary ( from_index, to_index) ;
488567 }
489568 (
490- Identifier :: Primary { index : from_index } ,
491- Identifier :: Secondary {
569+ Identifier :: PrimaryToSecondary {
570+ index : from_index, ..
571+ } ,
572+ Identifier :: SecondaryToSecondary {
573+ index : to_index,
574+ ts_kind,
575+ ..
576+ }
577+ | Identifier :: SecondaryToPrimary {
492578 index : to_index,
493579 ts_kind,
494580 ..
@@ -530,12 +616,17 @@ fn evaluate_chain<Cost: AStarCost>(
530616 chaining_cost_function. jump_12 ( from_index, to_index, ts_kind) ;
531617 }
532618 (
533- Identifier :: Secondary {
619+ Identifier :: SecondaryToSecondary {
534620 index : from_index,
535621 ts_kind,
536622 ..
537623 } ,
538- Identifier :: Secondary {
624+ Identifier :: SecondaryToSecondary {
625+ index : to_index,
626+ ts_kind : to_ts_kind,
627+ ..
628+ }
629+ | Identifier :: SecondaryToPrimary {
539630 index : to_index,
540631 ts_kind : to_ts_kind,
541632 ..
@@ -586,12 +677,17 @@ fn evaluate_chain<Cost: AStarCost>(
586677 chaining_cost_function. secondary ( from_index, to_index, ts_kind) ;
587678 }
588679 (
589- Identifier :: Secondary {
680+ Identifier :: SecondaryToPrimary {
590681 index : from_index,
591682 ts_kind,
592683 ..
593684 } ,
594- Identifier :: Primary { index : to_index } ,
685+ Identifier :: PrimaryToPrimary {
686+ index : to_index, ..
687+ }
688+ | Identifier :: PrimaryToSecondary {
689+ index : to_index, ..
690+ } ,
595691 ) => {
596692 let start = anchors. secondary ( from_index, ts_kind) . end ( ts_kind, k) ;
597693 let end = anchors. primary ( to_index) . start ( ) ;
@@ -630,7 +726,22 @@ fn evaluate_chain<Cost: AStarCost>(
630726 current_upper_bound +=
631727 chaining_cost_function. jump_34 ( from_index, to_index, ts_kind) ;
632728 }
633- ( Identifier :: End , _) | ( _, Identifier :: Start ) => unreachable ! ( ) ,
729+ ( Identifier :: End , _)
730+ | ( _, Identifier :: Start )
731+ | (
732+ Identifier :: SecondaryToPrimary { .. } | Identifier :: PrimaryToPrimary { .. } ,
733+ Identifier :: SecondaryToPrimary { .. } | Identifier :: SecondaryToSecondary { .. } ,
734+ )
735+ | (
736+ Identifier :: PrimaryToSecondary { .. } | Identifier :: SecondaryToSecondary { .. } ,
737+ Identifier :: PrimaryToPrimary { .. }
738+ | Identifier :: PrimaryToSecondary { .. }
739+ | Identifier :: End ,
740+ )
741+ | ( Identifier :: StartToPrimary { .. } | Identifier :: StartToSecondary { .. } , _)
742+ | ( _, Identifier :: StartToPrimary { .. } | Identifier :: StartToSecondary { .. } ) => {
743+ unreachable ! ( )
744+ }
634745 }
635746 }
636747
0 commit comments