48 #include "ConstrainedOptPack/src/AbstractLinAlgPack_MatrixSymAddDelUpdateable.hpp"
49 #include "ConstrainedOptPack/src/AbstractLinAlgPack_BFGS_helpers.hpp"
50 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_SpVectorClass.hpp"
52 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_MatrixOpOut.hpp"
53 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_GenPermMatrixSlice.hpp"
55 #include "AbstractLinAlgPack/src/AbstractLinAlgPack_GenPermMatrixSliceOut.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 bfgs_update_ptr_t& bfgs_update
73 : bfgs_update_(bfgs_update)
74 , act_set_frac_proj_start_(act_set_frac_proj_start)
75 , project_error_tol_(project_error_tol)
76 , super_basic_mult_drop_tol_(super_basic_mult_drop_tol)
97 out <<
"\n*** (PBFGS) Projected BFGS ...\n";
101 MHSB_t &rHL_super =
dynamic_cast<MHSB_t&
>(*rHL_k);
103 MHSB_t &rHL_super =
dyn_cast<MHSB_t>(*rHL_k);
110 const GenPermMatrixSlice
111 &Q_R = rHL_super.Q_R(),
112 &Q_X = rHL_super.Q_X();
114 bool do_projected_rHL_RR =
false;
118 sTy =
dot(*s_bfgs,*y_bfgs),
119 yTy =
dot(*y_bfgs,*y_bfgs);
123 && !bfgs_update().use_dampening()
127 out <<
"\nWarning! use_damening == false so there is no way we can perform any kind BFGS update (projected or not) so we will skip it!\n";
136 rHL_XX_scale = sTy > 0.0 ? yTy/sTy : 1.0;
141 if( !s->nu().updated_k(-1) ) {
143 out <<
"\nWarning! nu_k(-1) has not been updated. No adjustment to the set of superbasic variables is possible!\n";
146 else if( Q_R.is_identity() ) {
150 out <<
"\nDetermining if projected BFGS updating of superbasics should begin ...\n";
154 &nu_km1 = s->nu().get_k(-1);
156 nu_indep = nu_km1(s->var_indep());
159 ,act_set_frac_proj_start()
162 if( do_projected_rHL_RR ) {
166 typedef Workspace<size_type> i_x_t;
167 typedef Workspace<ConstrainedOptPack::EBounds> bnd_t;
168 i_x_t i_x_free(wss,n_pz);
169 i_x_t i_x_fixed(wss,n_pz);
170 bnd_t bnd_fixed(wss,n_pz);
171 i_x_t l_x_fixed_sorted(wss,n_pz);
173 value_type sRTBRRsR = 0.0, sRTyR = 0.0, sXTBXXsX = 0.0, sXTyX = 0.0;
177 nu_indep, *s_bfgs, *y_bfgs
178 , &n_pz_R, &i_x_free[0], &sRTBRRsR, &sRTyR );
181 out <<
"\nScaling for diagonal rHL_XX = rHL_XX_scale*I, rHL_XX_scale = " << rHL_XX_scale << std::endl;
183 Workspace<value_type> rHL_XX_diag_ws(wss,nu_indep.nz());
184 DVectorSlice rHL_XX_diag(&rHL_XX_diag_ws[0],rHL_XX_diag_ws.size());
185 rHL_XX_diag = rHL_XX_scale;
187 Workspace<value_type> Q_R_Q_RT_s_ws(wss,n_pz);
188 DVectorSlice Q_R_Q_RT_s(&Q_R_Q_RT_s_ws[0],Q_R_Q_RT_s_ws.size());
190 {
for(
size_type k = 0; k < n_pz_R; ++k ) {
192 Q_R_Q_RT_s(i) = (*s_bfgs)(i);
198 nu_indep,*s_bfgs,*y_bfgs,rHL_XX_diag,sRTBRRsR,sRTyR
199 ,&sXTBXXsX,&sXTyX,&l_x_fixed_sorted[0]);
202 project_error_tol(),super_basic_mult_drop_tol(),nu_indep
203 ,*s_bfgs,*y_bfgs,rHL_XX_diag,&l_x_fixed_sorted[0]
204 ,olevel,out,&sRTBRRsR,&sRTyR,&sXTBXXsX,&sXTyX
205 ,&n_pz_X,&n_pz_R,&i_x_free[0],&i_x_fixed[0],&bnd_fixed[0] );
210 MatrixSymAddDelUpdateable
211 &rHL_RR =
dynamic_cast<MatrixSymAddDelUpdateable&
>(
212 const_cast<MatrixSymWithOpFactorized&
>(*rHL_super.B_RR_ptr())
215 MatrixSymAddDelUpdateable
216 &rHL_RR =
dyn_cast<MatrixSymAddDelUpdateable>(
217 const_cast<MatrixSymWithOpFactorized&
>(*rHL_super.B_RR_ptr())
220 if( n_pz_R < n_pz ) {
222 out <<
"\nDeleting n_pz_X = " << n_pz_X <<
" rows/columns from rHL_RR for fixed independent variables...\n";
224 {
for(
size_type k = n_pz_X; k > 0; --k ) {
225 rHL_RR.delete_update( i_x_fixed[k-1],
false );
229 out <<
"\nrHL_RR after rows/columns where removed =\n" << *rHL_super.B_RR_ptr();
234 &rHL_XX =
dynamic_cast<MatrixSymInitDiag&
>(
235 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr())
239 &rHL_XX =
dyn_cast<MatrixSymInitDiag>(
240 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr())
243 rHL_XX.init_identity(n_pz_X,rHL_XX_scale);
245 rHL_super.initialize(
246 n_pz, n_pz_R, &i_x_free[0], &i_x_fixed[0], &bnd_fixed[0]
250 out <<
"\nFull rHL after reinitialization but before BFGS update:\n"
251 <<
"\nrHL =\n" << *rHL_k
252 <<
"\nQ_R =\n" << rHL_super.Q_R()
253 <<
"\nQ_X =\n" << rHL_super.Q_X();
257 do_projected_rHL_RR =
false;
259 out <<
"\nWith n_pz_X = " << n_pz_X <<
", there where no variables to drop from superbasis!\n";
267 out <<
"\nAdjust the set of superbasic variables and the projected reduced Hessian rHL_RR ...\n";
273 nu_indep = s->nu().get_k(-1)(s->var_indep());
277 typedef Workspace<size_type> i_x_t;
278 typedef Workspace<ConstrainedOptPack::EBounds> bnd_t;
279 i_x_t i_x_free(wss,n_pz);
280 i_x_t i_x_fixed(wss,n_pz);
281 bnd_t bnd_fixed(wss,n_pz);
282 i_x_t l_x_fixed_sorted(wss,n_pz);
284 value_type sRTBRRsR = 0.0, sRTyR = 0.0, sXTBXXsX = 0.0, sXTyX = 0.0;
288 nu_indep, *s_bfgs, *y_bfgs
289 , &n_pz_R, &i_x_free[0], &sRTBRRsR, &sRTyR );
295 out <<
"\nScaling for diagonal rHL_XX = rHL_XX_scale*I, rHL_XX_scale = " << rHL_XX_scale << std::endl;
297 Workspace<value_type> rHL_XX_diag_ws(wss,nu_indep.nz());
298 DVectorSlice rHL_XX_diag(&rHL_XX_diag_ws[0],rHL_XX_diag_ws.size());
299 rHL_XX_diag = rHL_XX_scale;
306 &rHL_XX =
dynamic_cast<MatrixSymInitDiag&
>(
307 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr())
311 &rHL_XX =
dyn_cast<MatrixSymInitDiag>(
312 const_cast<MatrixSymOp&
>(*rHL_super.B_XX_ptr())
315 rHL_XX.init_identity(rHL_XX.rows(),rHL_XX_scale);
318 Workspace<value_type> Q_R_Q_RT_s_ws(wss,n_pz);
319 DVectorSlice Q_R_Q_RT_s(&Q_R_Q_RT_s_ws[0],Q_R_Q_RT_s_ws.size());
321 {
for(
size_type k = 0; k < n_pz_R; ++k ) {
323 Q_R_Q_RT_s(i) = (*s_bfgs)(i);
328 nu_indep,*s_bfgs,*y_bfgs,rHL_XX_diag,sRTBRRsR,sRTyR
329 ,&sXTBXXsX,&sXTyX,&l_x_fixed_sorted[0]);
332 project_error_tol(),super_basic_mult_drop_tol(),nu_indep
333 ,*s_bfgs,*y_bfgs,rHL_XX_diag,&l_x_fixed_sorted[0]
334 ,olevel,out,&sRTBRRsR,&sRTyR,&sXTBXXsX,&sXTyX
335 ,&n_pz_X,&n_pz_R,&i_x_free[0],&i_x_fixed[0],&bnd_fixed[0] );
337 size_type num_free_to_fixed = 0, num_fixed_to_free = 0;
338 i_x_t i_x_free_to_fixed(wss,Q_R.cols());
339 i_x_t i_x_fixed_to_free(wss,Q_X.cols());
340 i_x_t i_x_free_still(wss,Q_R.cols());
341 std::fill_n( &i_x_free_still[0], Q_R.cols(), 0 );
343 GenPermMatrixSlice::const_iterator
344 Q_R_begin = Q_R.begin(),
348 *i_x_free_itr = &i_x_free[0],
349 *i_x_free_end = i_x_free_itr + n_pz_R;
351 if( Q_R_itr == Q_R_end && i_x_free_itr == i_x_free_end ) {
354 else if( i_x_free_itr == i_x_free_end ) {
356 i_x_free_to_fixed[num_free_to_fixed] = Q_R_itr->row_i();
360 else if( Q_R_itr == Q_R_end ) {
362 i_x_fixed_to_free[num_fixed_to_free] = *i_x_free_itr;
367 if( Q_R_itr->row_i() == *i_x_free_itr ) {
369 i_x_free_still[Q_R_itr-Q_R_begin] = Q_R_itr->row_i();
373 else if( Q_R_itr->row_i() < *i_x_free_itr ) {
375 i_x_free_to_fixed[num_free_to_fixed] = Q_R_itr->row_i();
381 i_x_fixed_to_free[num_fixed_to_free] = *i_x_free_itr;
389 out <<
"\nThere will be " << num_fixed_to_free <<
" independent variables added to the superbasis and rHL_RR";
391 out <<
" and their indexes are:\n";
392 for(
size_type k = 0; k < num_fixed_to_free; ++k)
393 out <<
" " << i_x_fixed_to_free[k];
399 out <<
"\nThere will be " << num_free_to_fixed <<
" independent variables removed from the superbasis and rHL_RR";
401 out <<
" and their indexes are:\n";
402 for(
size_type k = 0; k < num_free_to_fixed; ++k)
403 out <<
" " << i_x_free_to_fixed[k];
412 MatrixSymAddDelUpdateable
413 &rHL_RR =
dynamic_cast<MatrixSymAddDelUpdateable&
>(
414 const_cast<MatrixSymWithOpFactorized&
>(*rHL_super.B_RR_ptr())
417 MatrixSymAddDelUpdateable
418 &rHL_RR =
dyn_cast<MatrixSymAddDelUpdateable>(
419 const_cast<MatrixSymWithOpFactorized&
>(*rHL_super.B_RR_ptr())
423 if( num_free_to_fixed ) {
425 out <<
"\nDeleting " << num_free_to_fixed <<
" rows/columns from rHL_RR ...\n";
427 {
for(
size_type k = i_x_free_still.size(); k > 0; --k ) {
428 if( !i_x_free_still[k-1] )
429 rHL_RR.delete_update( k,
false );
433 out <<
"\nrHL_RR after rows/columns where removed =\n" << *rHL_super.B_RR_ptr();
437 if( num_fixed_to_free ) {
439 out <<
"\nAppending " << num_fixed_to_free <<
" rows/columns to rHL_RR ...\n";
441 {
for(
size_type k = 0; k < num_fixed_to_free; ++k ) {
442 rHL_RR.augment_update( NULL, rHL_XX_scale,
false );
446 out <<
"\nrHL_RR after rows/columns where appended =\n" << *rHL_super.B_RR_ptr();
452 {
for(
size_type k = 0; k < i_x_free_still.size(); ++k) {
453 if( i_x_free_still[k] ) {
454 i_x_free[tmp_n_pz_R] = i_x_free_still[k];
458 {
for(
size_type k = 0; k < num_fixed_to_free; ++k) {
459 i_x_free[tmp_n_pz_R] = i_x_fixed_to_free[k];
465 rHL_XX.init_identity(n_pz_X,rHL_XX_scale);
467 rHL_super.initialize(
468 n_pz, n_pz_R, &i_x_free[0], &i_x_fixed[0], &bnd_fixed[0]
472 out <<
"\nFull rHL after reinitialization but before BFGS update:\n"
473 <<
"\nrHL =\n" << *rHL_k
474 <<
"\nQ_R =\n" << rHL_super.Q_R()
475 <<
"\nQ_X =\n" << rHL_super.Q_X();
478 do_projected_rHL_RR =
true;
483 if( do_projected_rHL_RR ) {
486 const GenPermMatrixSlice
487 &Q_R = rHL_super.Q_R(),
488 &Q_X = rHL_super.Q_X();
494 Workspace<value_type>
495 y_bfgs_R_ws(wss,Q_R.cols()),
496 s_bfgs_R_ws(wss,Q_R.cols());
497 DVectorSlice y_bfgs_R(&y_bfgs_R_ws[0],y_bfgs_R_ws.size());
498 DVectorSlice s_bfgs_R(&s_bfgs_R_ws[0],s_bfgs_R_ws.size());
503 out <<
"\nPerform BFGS update on " << n_pz_R <<
" x " << n_pz_R <<
" projected reduced Hessian for the superbasic variables where B = rHL_RR...\n";
505 bfgs_update().perform_update(
506 &s_bfgs_R(),&y_bfgs_R(),first_update,out,olevel,algo->algo_cntr().check_results()
507 ,
const_cast<MatrixOp*
>(
static_cast<const MatrixOp*
>(rHL_super.B_RR_ptr().get()))
514 out <<
"\nPerform BFGS update on the full reduced Hessian where B = rHL...\n";
516 bfgs_update().perform_update(
517 s_bfgs,y_bfgs,first_update,out,olevel,algo->algo_cntr().check_results()
518 ,
const_cast<MatrixOp*
>(
static_cast<const MatrixOp*
>(rHL_super.B_RR_ptr().get()))
529 << L <<
"*** Perform BFGS update on only free independent (superbasic) variables.\n"
530 << L <<
"if s'*y < sqrt(macheps) * ||s||2 * ||y||2 and use_dampening == false then"
531 << L <<
" Skip the update and exit this step!\n"
533 << L <<
"rHL_XX_scale = max(y'*y/s'*y,1.0)\n"
534 << L <<
"do_projected_rHL_RR = false\n"
535 << L <<
"if nu_km1 is updated then\n"
536 << L <<
" if rHL_k.Q_R is the identity matrix then\n"
537 << L <<
" *** Determine if the active set has calmed down enough\n"
538 << L <<
" Given (num_active_indep,num_adds_indep,num_drops_indep) from act_set_stats_km1\n"
539 << L <<
" fact_same =\n"
540 << L <<
" ( num_adds_indep== NOT_KNOWN || num_drops_indep==NOT_KNOWN\n"
541 << L <<
" || num_active_indep==0\n"
543 << L <<
" : std::_MAX((num_active_indep-num_adds_indep-num_drops_indep)\n"
544 << L <<
" /num_active_indep,0.0)\n"
546 << L <<
" do_projected_rHL_RR\n"
547 << L <<
" = fact_same >= act_set_frac_proj_start && num_active_indep > 0\n"
548 << L <<
" if do_projected_rHL_RR == true then\n"
549 << L <<
" Determine the sets of superbasic variables given the mapping matrix\n"
550 << L <<
" Q = [ Q_R, Q_X ] where pz_R = Q_R'*pz <: R^n_pz_R are the superbasic variables and\n"
551 << L <<
" pz_X = Q_X'*pz <: R^n_pz_X are the nonbasic variables that only contain fixed\n"
552 << L <<
" variables in nu_km1(indep) where the following condidtions are satisfied:\n"
553 << L <<
" (s'*Q_X*rHL_XX_scale*Q_X'*s)/(s'*Q_R*Q_R'*rHL_k*Q_R*Q_R'*s) <= project_error_tol\n"
554 << L <<
" |s'*Q_X*Q_X'*y|/|s'*Q_R*Q_R'*s| <= project_error_tol\n"
555 << L <<
" |Q_X'*nu_km1(indep)|/||nu_km1(indep)||inf >= super_basic_mult_drop_tol\n"
556 << L <<
" if n_pz_R < n-r then\n"
557 << L <<
" Delete rows/columns of rHL_k to form rHL_RR = Q_R'*rHL_k*Q_R\n"
558 << L <<
" Define new rHL_k = [ Q_R, Q_X ] * [ rHL_RR, 0; 0; rHL_XX_scale*I ] [ Q_R'; Q_X ]\n"
560 << L <<
" do_projected_rHL_RR = false\n"
564 << L <<
" Determine the new Q_n = [ Q_R_n, Q_X_n ] that satisfies:\n"
565 << L <<
" (s'*Q_X_n*rHL_XX_scale*Q_X_n'*s)/(s'*Q_R_n*Q_R_n'*rHL_k*Q_R_n*Q_R_n'*s) <= project_error_tol\n"
566 << L <<
" |s'*Q_X_n*Q_X_n'*y|/|s'*Q_R_n*Q_R_n'*s| <= project_error_tol\n"
567 << L <<
" |Q_X_n'*nu_km1(indep)|/||nu_km1(indep)||inf >= super_basic_mult_drop_tol\n"
568 << L <<
" Remove rows/cols from rHL_k.rHL_RR for variables in rHL_k.Q_R that are not in Q_R_n.\n"
569 << L <<
" Add digonal entries equal to rHL_XX_scale to rHL_k.rHL_RR for variables in Q_R_n\n"
570 << L <<
" that are not in rHL_k.Q_R\n"
571 << L <<
" Define new rHL_k = [ Q_R_n, Q_X_n ] * [ rHL_k.rHL_RR, 0; 0; rHL_XX_scale*I ] [ Q_R_n'; Q_X_n ]\n"
572 << L <<
" do_projected_rHL_RR = true\n"
575 << L <<
"if do_projected_rHL_RR == true then\n"
576 << L <<
" Perform projected BFGS update (see below): (rHL_k.rHL_RR, Q_R_n'*s, Q_R_n'*y) -> rHL_k.rHL_RR\n"
578 << L <<
" Perform full BFGS update: (rHL_k, s, y) -> rHL_k\n"
579 << L <<
" begin BFGS update where B = rHL_k\n";
580 bfgs_update().print_step( out, L +
" " );
582 << L <<
" end BFGS update\n"
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
act_set_stats_iq_member act_set_stats_
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.
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
bool perform_update(DVectorSlice *s_bfgs, DVectorSlice *y_bfgs, bool first_update, std::ostream &out, EJournalOutputLevel olevel, NLPAlgo *algo, NLPAlgoState *s, MatrixOp *rHL_k)
quasi_newton_stats_iq_member quasi_newton_stats_
EJournalOutputLevel
enum for journal output.
T_To & dyn_cast(T_From &from)
void print_step(std::ostream &out, const std::string &leading_str) const
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...
ReducedHessianSecantUpdateBFGSProjected_Strategy(const bfgs_update_ptr_t &bfgs_update=NULL, value_type act_set_frac_proj_start=0.8, value_type project_error_tol=1e-5, value_type super_basic_mult_drop_tol=1e-5)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
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)