@@ -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
@@ -764,8 +765,14 @@ where
764765 // This should never happen because we set the AKKT tolerance
765766 // in the constructor and can never become `None` again
766767 let criterion_3 =
767- cache. panoc_cache . akkt_tolerance . unwrap ( ) <= self . epsilon_tolerance + SMALL_EPSILON ;
768- criterion_1 && criterion_2 && criterion_3
768+ cache
769+ . panoc_cache
770+ . akkt_tolerance
771+ . ok_or ( SolverError :: InvalidProblemState (
772+ "missing inner AKKT tolerance while checking the exit criterion" ,
773+ ) ) ?
774+ <= self . epsilon_tolerance + SMALL_EPSILON ;
775+ Ok ( criterion_1 && criterion_2 && criterion_3)
769776 }
770777
771778 /// Whether the penalty parameter should not be updated
@@ -802,13 +809,21 @@ where
802809 }
803810 }
804811
805- fn update_inner_akkt_tolerance ( & mut self ) {
812+ fn update_inner_akkt_tolerance ( & mut self ) -> FunctionCallResult {
806813 let cache = & mut self . alm_cache ;
807814 // epsilon_{nu+1} := max(epsilon, beta*epsilon_nu)
815+ let akkt_tolerance =
816+ cache
817+ . panoc_cache
818+ . akkt_tolerance
819+ . ok_or ( SolverError :: InvalidProblemState (
820+ "missing inner AKKT tolerance while updating it" ,
821+ ) ) ?;
808822 cache. panoc_cache . set_akkt_tolerance ( f64:: max (
809- cache . panoc_cache . akkt_tolerance . unwrap ( ) * self . epsilon_update_factor ,
823+ akkt_tolerance * self . epsilon_update_factor ,
810824 self . epsilon_tolerance ,
811825 ) ) ;
826+ Ok ( ( ) )
812827 }
813828
814829 fn final_cache_update ( & mut self ) {
@@ -843,7 +858,7 @@ where
843858 let mut inner_exit_status: ExitStatus = ExitStatus :: Converged ;
844859
845860 // Project y on Y
846- self . project_on_set_y ( ) ;
861+ self . project_on_set_y ( ) ? ;
847862
848863 // If the inner problem fails miserably, the failure should be propagated
849864 // upstream (using `?`). If the inner problem has not converged, that is fine,
@@ -867,7 +882,7 @@ where
867882 self . compute_alm_infeasibility ( ) ?; // ALM: ||y_plus - y||
868883
869884 // Check exit criterion
870- if self . is_exit_criterion_satisfied ( ) {
885+ if self . is_exit_criterion_satisfied ( ) ? {
871886 // Do not continue the outer iteration
872887 // An (epsilon, delta)-AKKT point has been found
873888 return Ok ( InnerProblemStatus :: new ( false , inner_exit_status) ) ;
@@ -876,7 +891,7 @@ where
876891 }
877892
878893 // Update inner problem tolerance
879- self . update_inner_akkt_tolerance ( ) ;
894+ self . update_inner_akkt_tolerance ( ) ? ;
880895
881896 // conclusive step: updated iteration count, resets PANOC cache,
882897 // sets f2_norm = f2_norm_plus etc
@@ -979,12 +994,11 @@ where
979994 . with_penalty ( c)
980995 . with_cost ( cost) ;
981996 if self . alm_problem . n1 > 0 {
982- let status = status. with_lagrange_multipliers (
983- self . alm_cache
984- . y_plus
985- . as_ref ( )
986- . expect ( "Although n1 > 0, there is no vector y (Lagrange multipliers)" ) ,
987- ) ;
997+ let status = status. with_lagrange_multipliers ( self . alm_cache . y_plus . as_ref ( ) . ok_or (
998+ SolverError :: InvalidProblemState (
999+ "missing Lagrange multipliers at the ALM solution" ,
1000+ ) ,
1001+ ) ?) ;
9881002 Ok ( status)
9891003 } else {
9901004 Ok ( status)
@@ -1129,7 +1143,7 @@ mod tests {
11291143 . with_initial_penalty ( 25.0 )
11301144 . with_initial_lagrange_multipliers ( & [ 2. , 3. , 4. , 10. ] ) ;
11311145
1132- alm_optimizer. project_on_set_y ( ) ;
1146+ alm_optimizer. project_on_set_y ( ) . unwrap ( ) ;
11331147 if let Some ( xi_after_proj) = & alm_optimizer. alm_cache . xi {
11341148 println ! ( "xi = {:#?}" , xi_after_proj) ;
11351149 let y_projected_correct = [
@@ -1282,7 +1296,7 @@ mod tests {
12821296 . with_initial_inner_tolerance ( 1e-1 )
12831297 . with_inner_tolerance_update_factor ( 0.2 ) ;
12841298
1285- alm_optimizer. update_inner_akkt_tolerance ( ) ;
1299+ alm_optimizer. update_inner_akkt_tolerance ( ) . unwrap ( ) ;
12861300
12871301 unit_test_utils:: assert_nearly_equal (
12881302 0.1 ,
@@ -1305,7 +1319,7 @@ mod tests {
13051319 ) ;
13061320
13071321 for _i in 1 ..=5 {
1308- alm_optimizer. update_inner_akkt_tolerance ( ) ;
1322+ alm_optimizer. update_inner_akkt_tolerance ( ) . unwrap ( ) ;
13091323 }
13101324 unit_test_utils:: assert_nearly_equal (
13111325 2e-5 ,
@@ -1411,20 +1425,20 @@ mod tests {
14111425
14121426 // should not exit yet...
14131427 assert ! (
1414- !alm_optimizer. is_exit_criterion_satisfied( ) ,
1428+ !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ,
14151429 "exists right away"
14161430 ) ;
14171431
14181432 let alm_optimizer = alm_optimizer
14191433 . with_initial_inner_tolerance ( 1e-3 )
14201434 . with_epsilon_tolerance ( 1e-3 ) ;
1421- assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1435+ assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14221436
14231437 alm_optimizer. alm_cache . delta_y_norm_plus = 1e-3 ;
1424- assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1438+ assert ! ( !alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14251439
14261440 alm_optimizer. alm_cache . f2_norm_plus = 1e-3 ;
1427- assert ! ( alm_optimizer. is_exit_criterion_satisfied( ) ) ;
1441+ assert ! ( alm_optimizer. is_exit_criterion_satisfied( ) . unwrap ( ) ) ;
14281442 }
14291443
14301444 #[ test]
0 commit comments