44 #include "MoochoPack_ReducedHessianSecantUpdateLPBFGS_Strategy.hpp"
45 #include "MoochoPack_PBFGS_helpers.hpp"
46 #include "MoochoPack_NLPAlgo.hpp"
47 #include "MoochoPack_NLPAlgoState.hpp"
48 #include "ConstrainedOptPack_MatrixSymPosDefLBFGS.hpp"
49 #include "ConstrainedOptPack/src/AbstractLinAlgPack_MatrixSymPosDefCholFactor.hpp"
50 #include "ConstrainedOptPack/src/AbstractLinAlgPack_BFGS_helpers.hpp"
51 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_SpVectorClass.hpp"
52 #include "AbstractLinAlgPack_SpVectorOp.hpp"
53 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixOpOut.hpp"
54 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_GenPermMatrixSlice.hpp"
55 #include "AbstractLinAlgPack_GenPermMatrixSliceOp.hpp"
56 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixSymInitDiag.hpp"
57 #include "DenseLinAlgPack_LinAlgOpPack.hpp"
58 #include "Midynamic_cast_verbose.h"
59 #include "MiWorkspacePack.h"
61 namespace LinAlgOpPack {
65 namespace MoochoPack {
68 const proj_bfgs_updater_ptr_t& proj_bfgs_updater
74 : proj_bfgs_updater_(proj_bfgs_updater)
75 , min_num_updates_proj_start_(min_num_updates_proj_start)
76 , max_num_updates_proj_start_(max_num_updates_proj_start)
77 , num_superbasics_switch_dense_(num_superbasics_switch_dense)
78 , num_add_recent_updates_(num_add_recent_updates)
82 DVectorSlice* s_bfgs, DVectorSlice* y_bfgs,
bool first_update
83 ,std::ostream& out, EJournalOutputLevel olevel, NLPAlgo *algo, NLPAlgoState *s
91 namespace rcp = MemMngPack;
93 using LinAlgOpPack::V_MtV;
95 using AbstractLinAlgPack::norm_inf;
101 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
102 out <<
"\n*** (LPBFGS) Full limited memory BFGS to projected BFGS ...\n";
106 MHSB_t &rHL_super =
dynamic_cast<MHSB_t&
>(*rHL_k);
108 MHSB_t &rHL_super =
dyn_cast<MHSB_t>(*rHL_k);
116 bool do_projected_rHL_RR =
false;
119 RCP<MatrixSymPosDefLBFGS>
120 lbfgs_rHL_RR = Teuchos::rcp_const_cast<MatrixSymPosDefLBFGS>(
121 Teuchos::rcp_dynamic_cast<
const MatrixSymPosDefLBFGS>(rHL_super.B_RR_ptr()) );
123 if( lbfgs_rHL_RR.get() && rHL_super.Q_R().is_identity() ) {
130 sTy =
dot(*s_bfgs,*y_bfgs),
131 yTy =
dot(*y_bfgs,*y_bfgs);
132 if( !ConstrainedOptPack::BFGS_sTy_suff_p_d(
134 ,
int(olevel) >=
int(PRINT_ALGORITHM_STEPS) ? &out : NULL )
135 && !proj_bfgs_updater().bfgs_update().use_dampening()
138 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
139 out <<
"\nWarning! use_damening == false so there is no way we can perform any"
140 " kind of BFGS update (projected or not) so we will skip it!\n";
142 quasi_newton_stats_(*s).set_k(0).set_updated_stats(
143 QuasiNewtonStats::INDEF_SKIPED );
147 const bool consider_switch = lbfgs_rHL_RR->num_secant_updates() >= min_num_updates_proj_start();
148 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
149 out <<
"\nnum_previous_updates = " << lbfgs_rHL_RR->num_secant_updates()
150 << ( consider_switch ?
" >= " :
" < " )
151 <<
"min_num_updates_proj_start = " << min_num_updates_proj_start()
153 ?
"\nConsidering if we should switch to projected BFGS updating of superbasics ...\n"
154 :
"\nNot time to consider switching to projected BFGS updating of superbasics yet!" );
156 if( consider_switch ) {
161 if( act_set_stats_(*s).updated_k(-1) ) {
162 if( static_cast<int>(olevel) >=
static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
163 out <<
"\nDetermining if projected BFGS updating of superbasics should begin ...\n";
167 &nu_km1 = s->nu().get_k(-1);
169 nu_indep = nu_km1(s->var_indep());
172 = PBFGSPack::act_set_calmed_down(
173 act_set_stats_(*s).get_k(-1)
174 ,proj_bfgs_updater().act_set_frac_proj_start()
177 max_num_updates_exceeded
178 = lbfgs_rHL_RR->m_bar() >= max_num_updates_proj_start();
179 do_projected_rHL_RR = act_set_calmed_down || max_num_updates_exceeded;
180 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
181 if( act_set_calmed_down ) {
182 out <<
"\nThe active set has calmed down enough so lets further consider switching to\n"
183 <<
"projected BFGS updating of superbasic variables ...\n";
185 else if( max_num_updates_exceeded ) {
186 out <<
"\nThe active set has not calmed down enough but num_previous_updates = "
187 << lbfgs_rHL_RR->m_bar() <<
" >= max_num_updates_proj_start = " << max_num_updates_proj_start()
188 <<
"\nso we will further consider switching to projected BFGS updating of superbasic variables ...\n";
191 out <<
"\nIt is not time to switch to projected BFGS so just keep performing full limited memory BFGS for now ...\n";
194 if( do_projected_rHL_RR ) {
198 typedef Workspace<size_type> i_x_t;
199 typedef Workspace<ConstrainedOptPack::EBounds> bnd_t;
200 i_x_t i_x_free(wss,n_pz);
201 i_x_t i_x_fixed(wss,n_pz);
202 bnd_t bnd_fixed(wss,n_pz);
203 i_x_t l_x_fixed_sorted(wss,n_pz);
207 rHL_scale = sTy > 0.0 ? yTy/sTy : 1.0;
208 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
209 out <<
"\nScaling for diagonal intitial rHL = rHL_scale*I, rHL_scale = " << rHL_scale << std::endl;
211 value_type sRTBRRsR = 0.0, sRTyR = 0.0, sXTBXXsX = 0.0, sXTyX = 0.0;
214 PBFGSPack::init_i_x_free_sRTsR_sRTyR(
215 nu_indep, *s_bfgs, *y_bfgs
216 , &n_pz_R, &i_x_free[0], &sRTBRRsR, &sRTyR );
217 sRTBRRsR *= rHL_scale;
218 Workspace<value_type> rHL_XX_diag_ws(wss,nu_indep.nz());
219 DVectorSlice rHL_XX_diag(&rHL_XX_diag_ws[0],rHL_XX_diag_ws.size());
220 rHL_XX_diag = rHL_scale;
223 PBFGSPack::sort_fixed_max_cond_viol(
224 nu_indep,*s_bfgs,*y_bfgs,rHL_XX_diag,sRTBRRsR,sRTyR
225 ,&sXTBXXsX,&sXTyX,&l_x_fixed_sorted[0]);
227 PBFGSPack::choose_fixed_free(
228 proj_bfgs_updater().project_error_tol()
229 ,proj_bfgs_updater().super_basic_mult_drop_tol(),nu_indep
230 ,*s_bfgs,*y_bfgs,rHL_XX_diag,&l_x_fixed_sorted[0]
231 ,olevel,out,&sRTBRRsR,&sRTyR,&sXTBXXsX,&sXTyX
232 ,&n_pz_X,&n_pz_R,&i_x_free[0],&i_x_fixed[0],&bnd_fixed[0] );
233 if( n_pz_R < n_pz ) {
239 low_num_super_basics = n_pz_R <= num_superbasics_switch_dense();
240 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_BASIC_ALGORITHM_INFO) ) {
241 out <<
"\nSwitching to projected BFGS updating ..."
242 <<
"\nn_pz_R = " << n_pz_R << ( low_num_super_basics ?
" <= " :
" > " )
243 <<
" num_superbasics_switch_dense = " << num_superbasics_switch_dense()
244 << ( low_num_super_basics
245 ?
"\nThere are not too many superbasic variables so use dense projected BFGS ...\n"
246 :
"\nThere are too many superbasic variables so use limited memory projected BFGS ...\n"
252 if( low_num_super_basics ) {
253 rHL_RR =
new MatrixSymPosDefCholFactor(
257 ,lbfgs_rHL_RR->maintain_original()
258 ,lbfgs_rHL_RR->maintain_inverse()
262 rHL_RR =
new MatrixSymPosDefLBFGS(
263 n_pz, lbfgs_rHL_RR->m()
264 ,lbfgs_rHL_RR->maintain_original()
265 ,lbfgs_rHL_RR->maintain_inverse()
266 ,lbfgs_rHL_RR->auto_rescaling()
269 rHL_RR->init_identity( n_pz_R, rHL_scale );
270 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
271 out <<
"\nrHL_RR after intialized to rHL_RR = rHL_scale*I but before performing current BFGS update:\nrHL_RR =\n"
272 <<
dynamic_cast<MatrixOp&
>(*rHL_RR);
277 &rHL_XX =
dynamic_cast<MatrixSymInitDiag&
>(
278 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr()));
281 &rHL_XX =
dyn_cast<MatrixSymInitDiag>(
282 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr()));
284 rHL_XX.init_identity( n_pz_X, rHL_scale );
286 rHL_super.initialize(
287 n_pz, n_pz_R, &i_x_free[0], &i_x_fixed[0], &bnd_fixed[0]
288 ,Teuchos::rcp_const_cast<const MatrixSymWithOpFactorized>(
289 Teuchos::rcp_dynamic_cast<MatrixSymWithOpFactorized>(rHL_RR))
296 &rHL_RR_op =
dynamic_cast<MatrixSymOp&
>(*rHL_RR);
297 const GenPermMatrixSlice
298 &Q_R = rHL_super.Q_R(),
299 &Q_X = rHL_super.Q_X();
301 Workspace<value_type>
302 y_bfgs_R_ws(wss,Q_R.cols()),
303 s_bfgs_R_ws(wss,Q_R.cols()),
304 y_bfgs_X_ws(wss,Q_X.cols()),
305 s_bfgs_X_ws(wss,Q_X.cols());
306 DVectorSlice y_bfgs_R(&y_bfgs_R_ws[0],y_bfgs_R_ws.size());
307 DVectorSlice s_bfgs_R(&s_bfgs_R_ws[0],s_bfgs_R_ws.size());
308 DVectorSlice y_bfgs_X(&y_bfgs_X_ws[0],y_bfgs_X_ws.size());
309 DVectorSlice s_bfgs_X(&s_bfgs_X_ws[0],s_bfgs_X_ws.size());
315 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
316 out <<
"\nPerform current BFGS update on " << n_pz_R <<
" x " << n_pz_R <<
" projected "
317 <<
"reduced Hessian for the superbasic variables where B = rHL_RR...\n";
319 QuasiNewtonStats quasi_newton_stats;
320 proj_bfgs_updater().bfgs_update().perform_update(
321 &s_bfgs_R(),&y_bfgs_R(),
false,out,olevel,algo->algo_cntr().check_results()
322 ,&rHL_RR_op, &quasi_newton_stats );
324 if( lbfgs_rHL_RR->m_bar() ) {
325 const size_type num_add_updates = std::_MIN(num_add_recent_updates(),lbfgs_rHL_RR->m_bar());
326 if( static_cast<int>(olevel) >=
static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
327 out <<
"\nAdd the min(num_previous_updates,num_add_recent_updates) = min(" << lbfgs_rHL_RR->m_bar()
328 <<
"," << num_add_recent_updates() <<
") = " << num_add_updates <<
" most recent BFGS updates if possible ...\n";
332 project_error_tol = proj_bfgs_updater().project_error_tol();
334 S = lbfgs_rHL_RR->S(),
335 Y = lbfgs_rHL_RR->Y();
337 for(
size_type l = 1; l <= num_add_updates; ++l, --k ) {
338 if(k == 0) k = lbfgs_rHL_RR->m_bar();
343 sRTyR =
dot( s_bfgs_R, y_bfgs_R );
344 sXTyX =
dot( s_bfgs_X, y_bfgs_X );
346 sXTyX_cond = ::fabs(sXTyX/sRTyR) <= project_error_tol,
347 do_update = sXTyX_cond,
348 sXTBXXsX_cond =
false;
354 sXTBXXsX = rHL_scale *
dot( s_bfgs_X, s_bfgs_X );
355 sXTBXXsX_cond = sXTBXXsX/sRTBRRsR <= project_error_tol;
356 do_update = sXTBXXsX_cond && sXTyX_cond;
358 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
359 out <<
"\n---------------------------------------------------------------------"
360 <<
"\nprevious update " << l
361 <<
"\n\nChecking projection error:\n"
362 <<
"\n|s_X'*y_X|/|s_R'*y_R| = |" << sXTyX <<
"|/|" << sRTyR
363 <<
"| = " << ::fabs(sXTyX/sRTyR)
364 << ( sXTyX_cond ?
" <= " :
" > " ) <<
" project_error_tol = "
365 << project_error_tol;
367 out <<
"\n(s_X'*rHL_XX*s_X/s_R'*rHL_RR*s_R) = (" << sXTBXXsX
368 <<
") = " << (sXTBXXsX/sRTBRRsR)
369 << ( sXTBXXsX_cond ?
" <= " :
" > " ) <<
" project_error_tol = "
370 << project_error_tol;
373 ?
"\n\nAttemping to add this previous update where B = rHL_RR ...\n"
374 :
"\n\nCan not add this previous update ...\n" );
379 proj_bfgs_updater().bfgs_update().perform_update(
380 &s_bfgs_R(),&y_bfgs_R(),
false,out,olevel,algo->algo_cntr().check_results()
381 ,&rHL_RR_op, &quasi_newton_stats );
383 catch(
const MatrixSymSecant::UpdateSkippedException& excpt ) {
384 if( static_cast<int>(olevel) >=
static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
385 out <<
"\nOops! The " << l <<
"th most recent BFGS update was rejected?:\n"
386 << excpt.what() << std::endl;
391 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
392 out <<
"\n---------------------------------------------------------------------\n";
394 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
395 out <<
"\nrHL_RR after adding previous BFGS updates:\nrHL_BRR =\n"
396 <<
dynamic_cast<MatrixOp&
>(*rHL_RR);
400 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
401 out <<
"\nThere were no previous update vectors to add!\n";
404 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
405 out <<
"\nFull rHL after complete reinitialization:\nrHL =\n" << *rHL_k;
407 quasi_newton_stats_(*s).set_k(0).set_updated_stats(
408 QuasiNewtonStats::REINITIALIZED );
412 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
413 out <<
"\nn_pz_R == n_pz = " << n_pz_R <<
", No variables would be removed from "
414 <<
"the superbasis so just keep on performing limited memory BFGS for now ...\n";
416 do_projected_rHL_RR =
false;
422 if(!do_projected_rHL_RR) {
423 if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
424 out <<
"\nPerform current BFGS update on " << n_pz <<
" x " << n_pz <<
" full "
425 <<
"limited memory reduced Hessian B = rHL ...\n";
427 proj_bfgs_updater().bfgs_update().perform_update(
428 s_bfgs,y_bfgs,first_update,out,olevel,algo->algo_cntr().check_results()
430 ,&quasi_newton_stats_(*s).set_k(0)
436 if( static_cast<int>(olevel) >=
static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
437 out <<
"\nWe have already switched to projected BFGS updating ...\n";
444 return proj_bfgs_updater().perform_update(
445 s_bfgs,y_bfgs,first_update,out,olevel,algo,s,rHL_k);
451 << L <<
"*** Perform limited memory LBFGS updating initially then switch to dense\n"
452 << L <<
"*** projected BFGS updating when appropriate.\n"
453 << L <<
"ToDo: Finish implementation!\n";
bool perform_update(DVectorSlice *s_bfgs, DVectorSlice *y_bfgs, bool first_update, std::ostream &out, EJournalOutputLevel olevel, NLPAlgo *algo, NLPAlgoState *s, MatrixOp *rHL_k)
T_To & dyn_cast(T_From &from)
value_type transVtMtV(const Vector &v_rhs1, const MatrixOp &M_rhs2, BLAS_Cpp::Transp trans_rhs2, const Vector &v_rhs3)
ReducedHessianSecantUpdateLPBFGS_Strategy(const proj_bfgs_updater_ptr_t &proj_bfgs_updater=NULL, size_type min_num_updates_proj_start=0, size_type max_num_updates_proj_start=999999, size_type num_superbasics_switch_dense=500, size_type num_add_recent_updates=10)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void Vp_StMtV(VectorMutable *v_lhs, value_type alpha, const MatrixOp &M_rhs1, BLAS_Cpp::Transp trans_rhs1, const Vector &v_rhs2, value_type beta=1.0)
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
void print_step(std::ostream &out, const std::string &leading_str) const
TEUCHOSCORE_LIB_DLL_EXPORT Teuchos::RCP< WorkspaceStore > get_default_workspace_store()