@@ -650,7 +650,7 @@ where
650650 . for_each ( |( ( y_plus_i, y_i) , w_alm_aux_i) | * y_plus_i = w_alm_aux_i + y_i / c) ;
651651
652652 // Step #3: y_plus := Proj_C(y_plus)
653- alm_set_c. project ( y_plus) ;
653+ alm_set_c. project ( y_plus) ? ;
654654
655655 // Step #4
656656 y_plus
@@ -667,7 +667,7 @@ where
667667 }
668668
669669 /// Project y on set Y
670- fn project_on_set_y ( & mut self ) {
670+ fn project_on_set_y ( & mut self ) -> FunctionCallResult {
671671 let problem = & self . alm_problem ;
672672 if let Some ( y_set) = & problem. alm_set_y {
673673 // NOTE: as_mut() converts from &mut Option<T> to Option<&mut T>
@@ -676,9 +676,10 @@ where
676676 // * which can be treated as Option<&mut [f64]>
677677 // * y_vec is &mut [f64]
678678 if let Some ( xi_vec) = self . alm_cache . xi . as_mut ( ) {
679- y_set. project ( & mut xi_vec[ 1 ..] ) ;
679+ y_set. project ( & mut xi_vec[ 1 ..] ) ? ;
680680 }
681681 }
682+ Ok ( ( ) )
682683 }
683684
684685 /// Solve inner problem
@@ -740,7 +741,7 @@ where
740741 inner_solver. solve ( u)
741742 }
742743
743- fn is_exit_criterion_satisfied ( & self ) -> bool {
744+ fn is_exit_criterion_satisfied ( & self ) -> Result < bool , SolverError > {
744745 let cache = & self . alm_cache ;
745746 let problem = & self . alm_problem ;
746747 // Criterion 1: ||Delta y|| <= c * delta
@@ -763,9 +764,14 @@ where
763764 // This function will panic is there is no akkt_tolerance
764765 // This should never happen because we set the AKKT tolerance
765766 // in the constructor and can never become `None` again
766- let criterion_3 =
767- cache. panoc_cache . akkt_tolerance . unwrap ( ) <= self . epsilon_tolerance + SMALL_EPSILON ;
768- criterion_1 && criterion_2 && criterion_3
767+ let criterion_3 = cache
768+ . panoc_cache
769+ . akkt_tolerance
770+ . ok_or ( SolverError :: InvalidProblemState (
771+ "missing inner AKKT tolerance while checking the exit criterion" ,
772+ ) ) ?
773+ <= self . epsilon_tolerance + SMALL_EPSILON ;
774+ Ok ( criterion_1 && criterion_2 && criterion_3)
769775 }
770776
771777 /// Whether the penalty parameter should not be updated
@@ -802,13 +808,20 @@ where
802808 }
803809 }
804810
805- fn update_inner_akkt_tolerance ( & mut self ) {
811+ fn update_inner_akkt_tolerance ( & mut self ) -> FunctionCallResult {
806812 let cache = & mut self . alm_cache ;
807813 // epsilon_{nu+1} := max(epsilon, beta*epsilon_nu)
814+ let akkt_tolerance = cache
815+ . panoc_cache
816+ . akkt_tolerance
817+ . ok_or ( SolverError :: InvalidProblemState (
818+ "missing inner AKKT tolerance while updating it" ,
819+ ) ) ?;
808820 cache. panoc_cache . set_akkt_tolerance ( f64:: max (
809- cache . panoc_cache . akkt_tolerance . unwrap ( ) * self . epsilon_update_factor ,
821+ akkt_tolerance * self . epsilon_update_factor ,
810822 self . epsilon_tolerance ,
811823 ) ) ;
824+ Ok ( ( ) )
812825 }
813826
814827 fn final_cache_update ( & mut self ) {
@@ -843,7 +856,7 @@ where
843856 let mut inner_exit_status: ExitStatus = ExitStatus :: Converged ;
844857
845858 // Project y on Y
846- self . project_on_set_y ( ) ;
859+ self . project_on_set_y ( ) ? ;
847860
848861 // If the inner problem fails miserably, the failure should be propagated
849862 // upstream (using `?`). If the inner problem has not converged, that is fine,
@@ -867,7 +880,7 @@ where
867880 self . compute_alm_infeasibility ( ) ?; // ALM: ||y_plus - y||
868881
869882 // Check exit criterion
870- if self . is_exit_criterion_satisfied ( ) {
883+ if self . is_exit_criterion_satisfied ( ) ? {
871884 // Do not continue the outer iteration
872885 // An (epsilon, delta)-AKKT point has been found
873886 return Ok ( InnerProblemStatus :: new ( false , inner_exit_status) ) ;
@@ -876,7 +889,7 @@ where
876889 }
877890
878891 // Update inner problem tolerance
879- self . update_inner_akkt_tolerance ( ) ;
892+ self . update_inner_akkt_tolerance ( ) ? ;
880893
881894 // conclusive step: updated iteration count, resets PANOC cache,
882895 // sets f2_norm = f2_norm_plus etc
@@ -983,7 +996,9 @@ where
983996 self . alm_cache
984997 . y_plus
985998 . as_ref ( )
986- . expect ( "Although n1 > 0, there is no vector y (Lagrange multipliers)" ) ,
999+ . ok_or ( SolverError :: InvalidProblemState (
1000+ "missing Lagrange multipliers at the ALM solution" ,
1001+ ) ) ?,
9871002 ) ;
9881003 Ok ( status)
9891004 } else {
@@ -1129,7 +1144,7 @@ mod tests {
11291144 . with_initial_penalty ( 25.0 )
11301145 . with_initial_lagrange_multipliers ( & [ 2. , 3. , 4. , 10. ] ) ;
11311146
1132- alm_optimizer. project_on_set_y ( ) ;
1147+ alm_optimizer. project_on_set_y ( ) . unwrap ( ) ;
11331148 if let Some ( xi_after_proj) = & alm_optimizer. alm_cache . xi {
11341149 println ! ( "xi = {:#?}" , xi_after_proj) ;
11351150 let y_projected_correct = [
@@ -1282,7 +1297,7 @@ mod tests {
12821297 . with_initial_inner_tolerance ( 1e-1 )
12831298 . with_inner_tolerance_update_factor ( 0.2 ) ;
12841299
1285- alm_optimizer. update_inner_akkt_tolerance ( ) ;
1300+ alm_optimizer. update_inner_akkt_tolerance ( ) . unwrap ( ) ;
12861301
12871302 unit_test_utils:: assert_nearly_equal (
12881303 0.1 ,
@@ -1305,7 +1320,7 @@ mod tests {
13051320 ) ;
13061321
13071322 for _i in 1 ..=5 {
1308- alm_optimizer. update_inner_akkt_tolerance ( ) ;
1323+ alm_optimizer. update_inner_akkt_tolerance ( ) . unwrap ( ) ;
13091324 }
13101325 unit_test_utils:: assert_nearly_equal (
13111326 2e-5 ,
@@ -1411,20 +1426,20 @@ mod tests {
14111426
14121427 // should not exit yet...
14131428 assert ! (
1414- !alm_optimizer. is_exit_criterion_satisfied( ) ,
1429+ !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ,
14151430 "exists right away"
14161431 ) ;
14171432
14181433 let alm_optimizer = alm_optimizer
14191434 . with_initial_inner_tolerance ( 1e-3 )
14201435 . with_epsilon_tolerance ( 1e-3 ) ;
1421- assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1436+ assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14221437
14231438 alm_optimizer. alm_cache . delta_y_norm_plus = 1e-3 ;
1424- assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1439+ assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14251440
14261441 alm_optimizer. alm_cache . f2_norm_plus = 1e-3 ;
1427- assert ! ( alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1442+ assert ! ( alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14281443 }
14291444
14301445 #[ test]
0 commit comments