49 #include "ConstrainedOptPack/src/AbstractLinAlgPack_MatrixSymPosDefCholFactor.hpp"
50 #include "ConstrainedOptPack/src/AbstractLinAlgPack_BFGS_helpers.hpp"
51 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_SpVectorClass.hpp"
53 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixOpOut.hpp"
54 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_GenPermMatrixSlice.hpp"
56 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixSymInitDiag.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)
91 namespace rcp = MemMngPack;
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);
135 && !proj_bfgs_updater().bfgs_update().use_dampening()
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";
147 const bool consider_switch = lbfgs_rHL_RR->num_secant_updates() >= min_num_updates_proj_start();
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 ) {
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());
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;
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;
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;
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;
224 nu_indep,*s_bfgs,*y_bfgs,rHL_XX_diag,sRTBRRsR,sRTyR
225 ,&sXTBXXsX,&sXTyX,&l_x_fixed_sorted[0]);
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();
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 );
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());
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());
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;
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 ) {
385 out <<
"\nOops! The " << l <<
"th most recent BFGS update was rejected?:\n"
386 << excpt.what() << std::endl;
392 out <<
"\n---------------------------------------------------------------------\n";
395 out <<
"\nrHL_RR after adding previous BFGS updates:\nrHL_BRR =\n"
396 <<
dynamic_cast<MatrixOp&
>(*rHL_RR);
401 out <<
"\nThere were no previous update vectors to add!\n";
405 out <<
"\nFull rHL after complete reinitialization:\nrHL =\n" << *rHL_k;
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) {
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()
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";
f_dbl_prec const f_int f_dbl_prec * Y
AbstractLinAlgPack::size_type size_type
void choose_fixed_free(const value_type project_error_tol, const value_type super_basic_mult_drop_tol, const SpVectorSlice &nu_indep, const DVectorSlice &s, const DVectorSlice &y, const DVectorSlice &B_XX, const size_type l_x_fixed_sorted[], EJournalOutputLevel olevel, std::ostream &out, value_type *sRTBRRsR, value_type *sRTyR, value_type *sXTBXXsX, value_type *sXTyX, size_type *n_pz_X, size_type *n_pz_R, size_type i_x_free[], size_type i_x_fixed[], ConstrainedOptPack::EBounds bnd_fixed[])
Choose the rest of i_x_free[] and i_x_fixed[].
SparseVector< SparseElement< index_type, value_type >, std::allocator< SparseElement< index_type, value_type > > > SpVector
bool perform_update(DVectorSlice *s_bfgs, DVectorSlice *y_bfgs, bool first_update, std::ostream &out, EJournalOutputLevel olevel, NLPAlgo *algo, NLPAlgoState *s, MatrixOp *rHL_k)
void init_i_x_free_sRTsR_sRTyR(const SpVectorSlice &nu_indep, const DVectorSlice &s, const DVectorSlice &y, size_type *n_pz_R, size_type i_x_free[], value_type *sRTsR, value_type *sRTyR)
Initialize i_x_free[], s_R'*s_R and s_R'*y_R for free variables not in nu_indep.
act_set_stats_iq_member act_set_stats_
value_type transVtMtV(const Vector &v_rhs1, const MatrixOp &M_rhs2, BLAS_Cpp::Transp trans_rhs2, const Vector &v_rhs3)
result = v_rhs1' * op(M_rhs2) * 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)
quasi_newton_stats_iq_member quasi_newton_stats_
EJournalOutputLevel
enum for journal output.
T_To & dyn_cast(T_From &from)
f_dbl_prec f_dbl_prec f_dbl_prec * S
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)
v_lhs = alpha * op(M_rhs1) * v_rhs2 + beta * v_lhs (BLAS xGEMV)
value_type norm_inf(const SparseVectorSlice< T_Ele > &sv_rhs)
result = ||sv_rhs||inf (BLAS IxAMAX)
bool BFGS_sTy_suff_p_d(const Vector &s, const Vector &y, const value_type *sTy=NULL, std::ostream *out=NULL, const char func_name[]=NULL)
Check that s'*y is sufficiently positive and print the result if it is not.
bool act_set_calmed_down(const ActSetStats &act_set_stats, const value_type act_set_frac_proj_start, EJournalOutputLevel olevel, std::ostream &out)
Determine if the active set has calmed down enough and print this test.
void sort_fixed_max_cond_viol(const SpVectorSlice &nu_indep, const DVectorSlice &s, const DVectorSlice &y, const DVectorSlice &B_XX, const value_type sRTBRRsR, const value_type sRTyR, value_type *sXTBXXsX, value_type *sXTyX, size_type l_x_fixed_sorted[])
Sort fixed variables according to the condition:
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
result = v_rhs1' * v_rhs2
SparseVectorSlice< SparseElement< index_type, value_type > > SpVectorSlice
DenseLinAlgPack::VectorSliceTmpl< value_type > DVectorSlice
void V_MtV(VectorMutable *v_lhs, const MatrixOp &M_rhs1, BLAS_Cpp::Transp trans_rhs1, const V &V_rhs2)
v_lhs = op(M_rhs1) * V_rhs2.
AbstractLinAlgPack::value_type value_type
Matrix class that represents a hessian matrix where only the super submatrix for the super basic vari...
DenseLinAlgPack::DMatrixSlice DMatrixSlice
void print_step(std::ostream &out, const std::string &leading_str) const
TEUCHOSCORE_LIB_DLL_EXPORT Teuchos::RCP< WorkspaceStore > get_default_workspace_store()
value_type dot(const DVectorSlice &vs_rhs1, const DVectorSlice &vs_rhs2)
result = vs_rhs1' * vs_rhs2 (BLAS xDOT)