|
MoochoPack : Framework for Large-Scale Optimization Algorithms Version of the Day
|
00001 #if 0 00002 00003 // @HEADER 00004 // *********************************************************************** 00005 // 00006 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization 00007 // Copyright (2003) Sandia Corporation 00008 // 00009 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00010 // license for use of this work by or on behalf of the U.S. Government. 00011 // 00012 // This library is free software; you can redistribute it and/or modify 00013 // it under the terms of the GNU Lesser General Public License as 00014 // published by the Free Software Foundation; either version 2.1 of the 00015 // License, or (at your option) any later version. 00016 // 00017 // This library is distributed in the hope that it will be useful, but 00018 // WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00020 // Lesser General Public License for more details. 00021 // 00022 // You should have received a copy of the GNU Lesser General Public 00023 // License along with this library; if not, write to the Free Software 00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00025 // USA 00026 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00027 // 00028 // *********************************************************************** 00029 // @HEADER 00030 00031 #include "MoochoPack_ReducedHessianSecantUpdateLPBFGS_Strategy.hpp" 00032 #include "MoochoPack_PBFGS_helpers.hpp" 00033 #include "MoochoPack_NLPAlgo.hpp" 00034 #include "MoochoPack_NLPAlgoState.hpp" 00035 #include "ConstrainedOptPack_MatrixSymPosDefLBFGS.hpp" 00036 #include "ConstrainedOptPack/src/AbstractLinAlgPack_MatrixSymPosDefCholFactor.hpp" 00037 #include "ConstrainedOptPack/src/AbstractLinAlgPack_BFGS_helpers.hpp" 00038 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_SpVectorClass.hpp" 00039 #include "AbstractLinAlgPack_SpVectorOp.hpp" 00040 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixOpOut.hpp" 00041 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_GenPermMatrixSlice.hpp" 00042 #include "AbstractLinAlgPack_GenPermMatrixSliceOp.hpp" 00043 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixSymInitDiag.hpp" 00044 #include "DenseLinAlgPack_LinAlgOpPack.hpp" 00045 #include "Midynamic_cast_verbose.h" 00046 #include "MiWorkspacePack.h" 00047 00048 namespace LinAlgOpPack { 00049 using AbstractLinAlgPack::Vp_StMtV; 00050 } 00051 00052 namespace MoochoPack { 00053 00054 ReducedHessianSecantUpdateLPBFGS_Strategy::ReducedHessianSecantUpdateLPBFGS_Strategy( 00055 const proj_bfgs_updater_ptr_t& proj_bfgs_updater 00056 ,size_type min_num_updates_proj_start 00057 ,size_type max_num_updates_proj_start 00058 ,size_type num_superbasics_switch_dense 00059 ,size_type num_add_recent_updates 00060 ) 00061 : proj_bfgs_updater_(proj_bfgs_updater) 00062 , min_num_updates_proj_start_(min_num_updates_proj_start) 00063 , max_num_updates_proj_start_(max_num_updates_proj_start) 00064 , num_superbasics_switch_dense_(num_superbasics_switch_dense) 00065 , num_add_recent_updates_(num_add_recent_updates) 00066 {} 00067 00068 bool ReducedHessianSecantUpdateLPBFGS_Strategy::perform_update( 00069 DVectorSlice* s_bfgs, DVectorSlice* y_bfgs, bool first_update 00070 ,std::ostream& out, EJournalOutputLevel olevel, NLPAlgo *algo, NLPAlgoState *s 00071 ,MatrixOp *rHL_k 00072 ) 00073 { 00074 using std::setw; 00075 using std::endl; 00076 using std::right; 00077 using Teuchos::dyn_cast; 00078 namespace rcp = MemMngPack; 00079 using Teuchos::RCP; 00080 using LinAlgOpPack::V_MtV; 00081 using DenseLinAlgPack::dot; 00082 using AbstractLinAlgPack::norm_inf; 00083 using AbstractLinAlgPack::transVtMtV; 00084 typedef ConstrainedOptPack::MatrixHessianSuperBasic MHSB_t; 00085 using Teuchos::Workspace; 00086 Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get(); 00087 00088 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00089 out << "\n*** (LPBFGS) Full limited memory BFGS to projected BFGS ...\n"; 00090 } 00091 00092 #ifdef _WINDOWS 00093 MHSB_t &rHL_super = dynamic_cast<MHSB_t&>(*rHL_k); 00094 #else 00095 MHSB_t &rHL_super = dyn_cast<MHSB_t>(*rHL_k); 00096 #endif 00097 00098 const size_type 00099 n = algo->nlp().n(), 00100 r = algo->nlp().r(), 00101 n_pz = n-r; 00102 00103 bool do_projected_rHL_RR = false; 00104 00105 // See if we still have a limited memory BFGS update matrix 00106 RCP<MatrixSymPosDefLBFGS> // We don't want this to be deleted until we are done with it 00107 lbfgs_rHL_RR = Teuchos::rcp_const_cast<MatrixSymPosDefLBFGS>( 00108 Teuchos::rcp_dynamic_cast<const MatrixSymPosDefLBFGS>(rHL_super.B_RR_ptr()) ); 00109 00110 if( lbfgs_rHL_RR.get() && rHL_super.Q_R().is_identity() ) { 00111 // 00112 // We have a limited memory BFGS matrix and have not started projected BFGS updating 00113 // yet so lets determine if it is time to consider switching 00114 // 00115 // Check that the current update is sufficiently p.d. before we do anything 00116 const value_type 00117 sTy = dot(*s_bfgs,*y_bfgs), 00118 yTy = dot(*y_bfgs,*y_bfgs); 00119 if( !ConstrainedOptPack::BFGS_sTy_suff_p_d( 00120 *s_bfgs,*y_bfgs,&sTy 00121 , int(olevel) >= int(PRINT_ALGORITHM_STEPS) ? &out : NULL ) 00122 && !proj_bfgs_updater().bfgs_update().use_dampening() 00123 ) 00124 { 00125 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00126 out << "\nWarning! use_damening == false so there is no way we can perform any" 00127 " kind of BFGS update (projected or not) so we will skip it!\n"; 00128 } 00129 quasi_newton_stats_(*s).set_k(0).set_updated_stats( 00130 QuasiNewtonStats::INDEF_SKIPED ); 00131 return true; 00132 } 00133 // Consider if we can even look at the active set yet. 00134 const bool consider_switch = lbfgs_rHL_RR->num_secant_updates() >= min_num_updates_proj_start(); 00135 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00136 out << "\nnum_previous_updates = " << lbfgs_rHL_RR->num_secant_updates() 00137 << ( consider_switch ? " >= " : " < " ) 00138 << "min_num_updates_proj_start = " << min_num_updates_proj_start() 00139 << ( consider_switch 00140 ? "\nConsidering if we should switch to projected BFGS updating of superbasics ...\n" 00141 : "\nNot time to consider switching to projected BFGS updating of superbasics yet!" ); 00142 } 00143 if( consider_switch ) { 00144 // 00145 // Our job here is to determine if it is time to switch to projected projected 00146 // BFGS updating. 00147 // 00148 if( act_set_stats_(*s).updated_k(-1) ) { 00149 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00150 out << "\nDetermining if projected BFGS updating of superbasics should begin ...\n"; 00151 } 00152 // Determine if the active set has calmed down enough 00153 const SpVector 00154 &nu_km1 = s->nu().get_k(-1); 00155 const SpVectorSlice 00156 nu_indep = nu_km1(s->var_indep()); 00157 const bool 00158 act_set_calmed_down 00159 = PBFGSPack::act_set_calmed_down( 00160 act_set_stats_(*s).get_k(-1) 00161 ,proj_bfgs_updater().act_set_frac_proj_start() 00162 ,olevel,out 00163 ), 00164 max_num_updates_exceeded 00165 = lbfgs_rHL_RR->m_bar() >= max_num_updates_proj_start(); 00166 do_projected_rHL_RR = act_set_calmed_down || max_num_updates_exceeded; 00167 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00168 if( act_set_calmed_down ) { 00169 out << "\nThe active set has calmed down enough so lets further consider switching to\n" 00170 << "projected BFGS updating of superbasic variables ...\n"; 00171 } 00172 else if( max_num_updates_exceeded ) { 00173 out << "\nThe active set has not calmed down enough but num_previous_updates = " 00174 << lbfgs_rHL_RR->m_bar() << " >= max_num_updates_proj_start = " << max_num_updates_proj_start() 00175 << "\nso we will further consider switching to projected BFGS updating of superbasic variables ...\n"; 00176 } 00177 else { 00178 out << "\nIt is not time to switch to projected BFGS so just keep performing full limited memory BFGS for now ...\n"; 00179 } 00180 } 00181 if( do_projected_rHL_RR ) { 00182 // 00183 // Determine the set of initially fixed and free independent variables. 00184 // 00185 typedef Workspace<size_type> i_x_t; 00186 typedef Workspace<ConstrainedOptPack::EBounds> bnd_t; 00187 i_x_t i_x_free(wss,n_pz); 00188 i_x_t i_x_fixed(wss,n_pz); 00189 bnd_t bnd_fixed(wss,n_pz); 00190 i_x_t l_x_fixed_sorted(wss,n_pz); 00191 size_type n_pz_X = 0, n_pz_R = 0; 00192 // rHL = rHL_scale * I 00193 value_type 00194 rHL_scale = sTy > 0.0 ? yTy/sTy : 1.0; 00195 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00196 out << "\nScaling for diagonal intitial rHL = rHL_scale*I, rHL_scale = " << rHL_scale << std::endl; 00197 } 00198 value_type sRTBRRsR = 0.0, sRTyR = 0.0, sXTBXXsX = 0.0, sXTyX = 0.0; 00199 // Get the elements in i_x_free[] for variables that are definitely free 00200 // and initialize s_R'*B_RR*s_R and s_R'*y_R 00201 PBFGSPack::init_i_x_free_sRTsR_sRTyR( 00202 nu_indep, *s_bfgs, *y_bfgs 00203 , &n_pz_R, &i_x_free[0], &sRTBRRsR, &sRTyR ); 00204 sRTBRRsR *= rHL_scale; 00205 Workspace<value_type> rHL_XX_diag_ws(wss,nu_indep.nz()); 00206 DVectorSlice rHL_XX_diag(&rHL_XX_diag_ws[0],rHL_XX_diag_ws.size()); 00207 rHL_XX_diag = rHL_scale; 00208 // Sort fixed variables according to |s_X(i)^2*B_XX(i,i)|/|sRTBRRsR| + |s_X(i)*y_X(i)|/|sRTyR| 00209 // and initialize s_X'*B_XX*s_X and s_X*y_X 00210 PBFGSPack::sort_fixed_max_cond_viol( 00211 nu_indep,*s_bfgs,*y_bfgs,rHL_XX_diag,sRTBRRsR,sRTyR 00212 ,&sXTBXXsX,&sXTyX,&l_x_fixed_sorted[0]); 00213 // Pick initial set of i_x_free[] and i_x_fixed[] (sorted!) 00214 PBFGSPack::choose_fixed_free( 00215 proj_bfgs_updater().project_error_tol() 00216 ,proj_bfgs_updater().super_basic_mult_drop_tol(),nu_indep 00217 ,*s_bfgs,*y_bfgs,rHL_XX_diag,&l_x_fixed_sorted[0] 00218 ,olevel,out,&sRTBRRsR,&sRTyR,&sXTBXXsX,&sXTyX 00219 ,&n_pz_X,&n_pz_R,&i_x_free[0],&i_x_fixed[0],&bnd_fixed[0] ); 00220 if( n_pz_R < n_pz ) { 00221 // 00222 // We are ready to transition to projected BFGS updating! 00223 // 00224 // Determine if we are be using dense or limited memory BFGS? 00225 const bool 00226 low_num_super_basics = n_pz_R <= num_superbasics_switch_dense(); 00227 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_BASIC_ALGORITHM_INFO) ) { 00228 out << "\nSwitching to projected BFGS updating ..." 00229 << "\nn_pz_R = " << n_pz_R << ( low_num_super_basics ? " <= " : " > " ) 00230 << " num_superbasics_switch_dense = " << num_superbasics_switch_dense() 00231 << ( low_num_super_basics 00232 ? "\nThere are not too many superbasic variables so use dense projected BFGS ...\n" 00233 : "\nThere are too many superbasic variables so use limited memory projected BFGS ...\n" 00234 ); 00235 } 00236 // Create new matrix to use for rHL_RR initialized to rHL_RR = rHL_scale*I 00237 RCP<MatrixSymSecant> 00238 rHL_RR = NULL; 00239 if( low_num_super_basics ) { 00240 rHL_RR = new MatrixSymPosDefCholFactor( 00241 NULL // Let it allocate its own memory 00242 ,NULL // ... 00243 ,n_pz // maximum size 00244 ,lbfgs_rHL_RR->maintain_original() 00245 ,lbfgs_rHL_RR->maintain_inverse() 00246 ); 00247 } 00248 else { 00249 rHL_RR = new MatrixSymPosDefLBFGS( 00250 n_pz, lbfgs_rHL_RR->m() 00251 ,lbfgs_rHL_RR->maintain_original() 00252 ,lbfgs_rHL_RR->maintain_inverse() 00253 ,lbfgs_rHL_RR->auto_rescaling() 00254 ); 00255 } 00256 rHL_RR->init_identity( n_pz_R, rHL_scale ); 00257 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) { 00258 out << "\nrHL_RR after intialized to rHL_RR = rHL_scale*I but before performing current BFGS update:\nrHL_RR =\n" 00259 << dynamic_cast<MatrixOp&>(*rHL_RR); // I know this is okay! 00260 } 00261 // Initialize rHL_XX = rHL_scale*I 00262 #ifdef _WINDOWS 00263 MatrixSymInitDiag 00264 &rHL_XX = dynamic_cast<MatrixSymInitDiag&>( 00265 const_cast<MatrixSymOp&>(*rHL_super.B_XX_ptr())); 00266 #else 00267 MatrixSymInitDiag 00268 &rHL_XX = dyn_cast<MatrixSymInitDiag>( 00269 const_cast<MatrixSymOp&>(*rHL_super.B_XX_ptr())); 00270 #endif 00271 rHL_XX.init_identity( n_pz_X, rHL_scale ); 00272 // Reinitialize rHL 00273 rHL_super.initialize( 00274 n_pz, n_pz_R, &i_x_free[0], &i_x_fixed[0], &bnd_fixed[0] 00275 ,Teuchos::rcp_const_cast<const MatrixSymWithOpFactorized>( 00276 Teuchos::rcp_dynamic_cast<MatrixSymWithOpFactorized>(rHL_RR)) 00277 ,NULL,BLAS_Cpp::no_trans,rHL_super.B_XX_ptr() 00278 ); 00279 // 00280 // Perform the current BFGS update first 00281 // 00282 MatrixSymOp 00283 &rHL_RR_op = dynamic_cast<MatrixSymOp&>(*rHL_RR); 00284 const GenPermMatrixSlice 00285 &Q_R = rHL_super.Q_R(), 00286 &Q_X = rHL_super.Q_X(); 00287 // Get projected BFGS update vectors y_bfgs_R, s_bfgs_R 00288 Workspace<value_type> 00289 y_bfgs_R_ws(wss,Q_R.cols()), 00290 s_bfgs_R_ws(wss,Q_R.cols()), 00291 y_bfgs_X_ws(wss,Q_X.cols()), 00292 s_bfgs_X_ws(wss,Q_X.cols()); 00293 DVectorSlice y_bfgs_R(&y_bfgs_R_ws[0],y_bfgs_R_ws.size()); 00294 DVectorSlice s_bfgs_R(&s_bfgs_R_ws[0],s_bfgs_R_ws.size()); 00295 DVectorSlice y_bfgs_X(&y_bfgs_X_ws[0],y_bfgs_X_ws.size()); 00296 DVectorSlice s_bfgs_X(&s_bfgs_X_ws[0],s_bfgs_X_ws.size()); 00297 V_MtV( &y_bfgs_R, Q_R, BLAS_Cpp::trans, *y_bfgs ); // y_bfgs_R = Q_R'*y_bfgs 00298 V_MtV( &s_bfgs_R, Q_R, BLAS_Cpp::trans, *s_bfgs ); // s_bfgs_R = Q_R'*s_bfgs 00299 V_MtV( &y_bfgs_X, Q_X, BLAS_Cpp::trans, *y_bfgs ); // y_bfgs_X = Q_X'*y_bfgs 00300 V_MtV( &s_bfgs_X, Q_X, BLAS_Cpp::trans, *s_bfgs ); // s_bfgs_X = Q_X'*s_bfgs 00301 // Update rHL_RR 00302 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00303 out << "\nPerform current BFGS update on " << n_pz_R << " x " << n_pz_R << " projected " 00304 << "reduced Hessian for the superbasic variables where B = rHL_RR...\n"; 00305 } 00306 QuasiNewtonStats quasi_newton_stats; 00307 proj_bfgs_updater().bfgs_update().perform_update( 00308 &s_bfgs_R(),&y_bfgs_R(),false,out,olevel,algo->algo_cntr().check_results() 00309 ,&rHL_RR_op, &quasi_newton_stats ); 00310 // Perform previous updates if possible 00311 if( lbfgs_rHL_RR->m_bar() ) { 00312 const size_type num_add_updates = std::_MIN(num_add_recent_updates(),lbfgs_rHL_RR->m_bar()); 00313 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00314 out << "\nAdd the min(num_previous_updates,num_add_recent_updates) = min(" << lbfgs_rHL_RR->m_bar() 00315 << "," << num_add_recent_updates() << ") = " << num_add_updates << " most recent BFGS updates if possible ...\n"; 00316 } 00317 // Now add previous update vectors 00318 const value_type 00319 project_error_tol = proj_bfgs_updater().project_error_tol(); 00320 const DMatrixSlice 00321 S = lbfgs_rHL_RR->S(), 00322 Y = lbfgs_rHL_RR->Y(); 00323 size_type k = lbfgs_rHL_RR->k_bar(); // Location in S and Y of most recent update vectors 00324 for( size_type l = 1; l <= num_add_updates; ++l, --k ) { 00325 if(k == 0) k = lbfgs_rHL_RR->m_bar(); // see MatrixSymPosDefLBFGS 00326 // Check to see if this update satisfies the required conditions. 00327 // Start with the condition on s'*y since this are cheap to check. 00328 V_MtV( &s_bfgs_X(), Q_X, BLAS_Cpp::trans, S.col(k) ); // s_bfgs_X = Q_X'*s_bfgs 00329 V_MtV( &y_bfgs_X(), Q_X, BLAS_Cpp::trans, Y.col(k) ); // y_bfgs_X = Q_X'*y_bfgs 00330 sRTyR = dot( s_bfgs_R, y_bfgs_R ); 00331 sXTyX = dot( s_bfgs_X, y_bfgs_X ); 00332 bool 00333 sXTyX_cond = ::fabs(sXTyX/sRTyR) <= project_error_tol, 00334 do_update = sXTyX_cond, 00335 sXTBXXsX_cond = false; 00336 if( sXTyX_cond ) { 00337 // Check the second more expensive condition 00338 V_MtV( &s_bfgs_R(), Q_R, BLAS_Cpp::trans, S.col(k) ); // s_bfgs_R = Q_R'*s_bfgs 00339 V_MtV( &y_bfgs_R(), Q_R, BLAS_Cpp::trans, Y.col(k) ); // y_bfgs_R = Q_R'*y_bfgs 00340 sRTBRRsR = transVtMtV( s_bfgs_R, rHL_RR_op, BLAS_Cpp::no_trans, s_bfgs_R ); 00341 sXTBXXsX = rHL_scale * dot( s_bfgs_X, s_bfgs_X ); 00342 sXTBXXsX_cond = sXTBXXsX/sRTBRRsR <= project_error_tol; 00343 do_update = sXTBXXsX_cond && sXTyX_cond; 00344 } 00345 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00346 out << "\n---------------------------------------------------------------------" 00347 << "\nprevious update " << l 00348 << "\n\nChecking projection error:\n" 00349 << "\n|s_X'*y_X|/|s_R'*y_R| = |" << sXTyX << "|/|" << sRTyR 00350 << "| = " << ::fabs(sXTyX/sRTyR) 00351 << ( sXTyX_cond ? " <= " : " > " ) << " project_error_tol = " 00352 << project_error_tol; 00353 if( sXTyX_cond ) { 00354 out << "\n(s_X'*rHL_XX*s_X/s_R'*rHL_RR*s_R) = (" << sXTBXXsX 00355 << ") = " << (sXTBXXsX/sRTBRRsR) 00356 << ( sXTBXXsX_cond ? " <= " : " > " ) << " project_error_tol = " 00357 << project_error_tol; 00358 } 00359 out << ( do_update 00360 ? "\n\nAttemping to add this previous update where B = rHL_RR ...\n" 00361 : "\n\nCan not add this previous update ...\n" ); 00362 } 00363 if( do_update ) { 00364 // ( rHL_RR, s_bfgs_R, y_bfgs_R ) -> rHL_RR (this should not throw an exception!) 00365 try { 00366 proj_bfgs_updater().bfgs_update().perform_update( 00367 &s_bfgs_R(),&y_bfgs_R(),false,out,olevel,algo->algo_cntr().check_results() 00368 ,&rHL_RR_op, &quasi_newton_stats ); 00369 } 00370 catch( const MatrixSymSecant::UpdateSkippedException& excpt ) { 00371 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00372 out << "\nOops! The " << l << "th most recent BFGS update was rejected?:\n" 00373 << excpt.what() << std::endl; 00374 } 00375 } 00376 } 00377 } 00378 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00379 out << "\n---------------------------------------------------------------------\n"; 00380 } 00381 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) { 00382 out << "\nrHL_RR after adding previous BFGS updates:\nrHL_BRR =\n" 00383 << dynamic_cast<MatrixOp&>(*rHL_RR); 00384 } 00385 } 00386 else { 00387 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00388 out << "\nThere were no previous update vectors to add!\n"; 00389 } 00390 } 00391 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) { 00392 out << "\nFull rHL after complete reinitialization:\nrHL =\n" << *rHL_k; 00393 } 00394 quasi_newton_stats_(*s).set_k(0).set_updated_stats( 00395 QuasiNewtonStats::REINITIALIZED ); 00396 return true; 00397 } 00398 else { 00399 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00400 out << "\nn_pz_R == n_pz = " << n_pz_R << ", No variables would be removed from " 00401 << "the superbasis so just keep on performing limited memory BFGS for now ...\n"; 00402 } 00403 do_projected_rHL_RR = false; 00404 } 00405 } 00406 } 00407 } 00408 // If we have not switched to PBFGS then just update the full limited memory BFGS matrix 00409 if(!do_projected_rHL_RR) { 00410 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00411 out << "\nPerform current BFGS update on " << n_pz << " x " << n_pz << " full " 00412 << "limited memory reduced Hessian B = rHL ...\n"; 00413 } 00414 proj_bfgs_updater().bfgs_update().perform_update( 00415 s_bfgs,y_bfgs,first_update,out,olevel,algo->algo_cntr().check_results() 00416 ,lbfgs_rHL_RR.get() 00417 ,&quasi_newton_stats_(*s).set_k(0) 00418 ); 00419 return true; 00420 } 00421 } 00422 else { 00423 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { 00424 out << "\nWe have already switched to projected BFGS updating ...\n"; 00425 } 00426 } 00427 // 00428 // If we get here then we must have switched to 00429 // projected updating so lets just pass it on! 00430 // 00431 return proj_bfgs_updater().perform_update( 00432 s_bfgs,y_bfgs,first_update,out,olevel,algo,s,rHL_k); 00433 } 00434 00435 void ReducedHessianSecantUpdateLPBFGS_Strategy::print_step( std::ostream& out, const std::string& L ) const 00436 { 00437 out 00438 << L << "*** Perform limited memory LBFGS updating initially then switch to dense\n" 00439 << L << "*** projected BFGS updating when appropriate.\n" 00440 << L << "ToDo: Finish implementation!\n"; 00441 } 00442 00443 } // end namespace MoochoPack 00444 00445 #endif // 0
1.7.4