58 namespace MoochoPack {
61 bool rescale_init_identity
67 :rescale_init_identity_(rescale_init_identity)
68 ,use_dampening_(use_dampening)
69 ,secant_testing_(secant_testing)
70 ,secant_warning_tol_(secant_warning_tol)
71 ,secant_error_tol_(secant_error_tol)
76 ,VectorMutable *y_bfgs
85 namespace rcp = MemMngPack;
100 yTy = NOT_CALCULATED;
101 bool used_dampening =
false;
104 if( sTy == NOT_CALCULATED )
105 sTy =
dot( *s_bfgs, *y_bfgs );
108 out <<
"\n(y'*s) == 0, skipping the update ...\n";
115 &B_updatable =
dyn_cast<MatrixSymSecant>(*B);
125 if( first_update && rescale_init_identity() ) {
126 if( sTy == NOT_CALCULATED )
127 sTy =
dot( *s_bfgs, *y_bfgs );
128 if( yTy == NOT_CALCULATED )
129 yTy =
dot( *y_bfgs, *y_bfgs );
133 Iscale_too_small = 1e-5;
134 if( Iscale >= Iscale_too_small ) {
136 out <<
"\nRescaling the initial identity matrix before the update as:\n"
137 <<
"Iscale = (y'*y)/(y'*s) = ("<<yTy<<
")/("<<sTy<<
") = "<<Iscale<<
"\n"
138 <<
"B = Iscale * eye(n-r) ...\n";
140 B_updatable.init_identity( y_bfgs->space(), Iscale );
142 out <<
"\nB after rescaling = \n" << *
B;
147 out <<
"\nSkipping rescaling of the initial identity matrix since:\n"
148 <<
"Iscale = (y'*y)/(y'*s) = ("<<yTy<<
")/("<<sTy<<
") = "<<Iscale
149 <<
" < Iscale_too_small = " << Iscale_too_small << std::endl;
156 VectorSpace::vec_mut_ptr_t
158 if( use_dampening() ) {
162 <<
"\nConsidering the dampened update ...\n";
165 Bs = y_bfgs->space().create_member();
168 if( sTy == NOT_CALCULATED )
169 sTy =
dot( *s_bfgs, *y_bfgs );
174 theta = ( sTy >= 0.2 * sTBs )
176 : (0.8 * sTBs ) / ( sTBs - sTy );
180 <<
"\ns_bfgs'*y_bfgs = " << sTy
181 << ( theta == 1.0 ?
" >= " :
" < " )
182 <<
" s_bfgs' * B * s_bfgs = " << sTBs << std::endl;
188 <<
"Perform the undamped update ...\n";
193 Vt_S( y_bfgs, theta );
194 Vp_StV( y_bfgs, (1.0-theta), *Bs );
199 <<
"Dampen the update ...\n"
200 <<
"theta = " << theta << std::endl
201 <<
"y_bfgs = theta*y_bfgs + (1-theta)*B*s_bfgs ...\n"
202 <<
"||y_bfgs||inf = " << y_bfgs->norm_inf() << std::endl;
208 <<
"y_bfgs =\n" << *y_bfgs;
211 used_dampening =
true;
217 VectorSpace::vec_mut_ptr_t
220 if( check_results ) {
222 s_bfgs_save = s_bfgs->clone();
223 y_bfgs_save = y_bfgs->clone();
226 B_updatable.secant_update(
232 catch(
const MatrixSymSecant::UpdateFailedException& excpt ) {
234 out <<
"\nThe factorization of B failed in a major way! Rethrow!\n";
238 catch(
const MatrixSymSecant::UpdateSkippedException& excpt ) {
240 out << excpt.what() << std::endl
241 <<
"\nSkipping BFGS update. B = B ...\n";
249 out <<
"\nB after the BFGS update = \n" << *
B;
257 *B, *s_bfgs_save, *y_bfgs_save
258 , secant_warning_tol(), secant_error_tol()
265 msg[] =
"Error, the secant property for the BFGS update failed\n"
266 "Stopping the algorithm ...\n";
270 ,
" BFGSUpdate_Strategy::perform_update(...) : " << msg );
283 << L <<
"if use_dampening == true then\n"
284 << L <<
" if s'*y >= 0.2 * s'*B*s then\n"
285 << L <<
" theta = 1.0\n"
287 << L <<
" theta = 0.8*s'*B*s / (s'*B*s - s'*y)\n"
289 << L <<
" y = theta*y + (1-theta)*B*s\n"
291 << L <<
"if first_update && rescale_init_identity and y'*s is sufficently positive then\n"
292 << L <<
" B = |(y'*y)/(y'*s)| * eye(size(s))\n"
294 << L <<
"if s'*y is sufficently positive then\n"
295 << L <<
" *** Peform BFGS update\n"
296 << L <<
" (B, s, y ) -> B (through MatrixSymSecantUpdate interface)\n"
297 << L <<
" if ( check_results && secant_testing == SECANT_TEST_DEFAULT )\n"
298 << L <<
" or ( secant_testing == SECANT_TEST_ALWAYS ) then\n"
299 << L <<
" if B*s != y then\n"
300 << L <<
" *** The secant condition does not check out\n"
301 << L <<
" Throw TestFailed!\n"
BFGSUpdate_Strategy(bool rescale_init_identity=true, bool use_dampening=true, ESecantTesting secant_testing=SECANT_TEST_DEFAULT, value_type secant_warning_tol=1e-6, value_type secant_error_tol=1e-1)
void print_step(std::ostream &out, const std::string &leading_str) const
void Vt_S(VectorMutable *v_lhs, const value_type &alpha)
v_lhs *= alpha
Thrown if a runtime test failed.
Class for storing statistics about the Quasi-Newton updating.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void Vp_StV(VectorMutable *v_lhs, const value_type &alpha, const Vector &v_rhs)
v_lhs = alpha * v_rhs + v_lhs
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &V_rhs)
v_lhs = alpha * V_rhs.
void perform_update(VectorMutable *s_bfgs, VectorMutable *y_bfgs, bool first_update, std::ostream &out, EJournalOutputLevel olevel, bool check_results, MatrixSymOp *B, QuasiNewtonStats *quasi_newton_stats)
Perform the BFGS update.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
EJournalOutputLevel
enum for journal output.
T_To & dyn_cast(T_From &from)
void V_VpV(VectorMutable *v_lhs, const V1 &V1_rhs1, const V2 &V2_rhs2)
const LAPACK_C_Decl::f_int const LAPACK_C_Decl::f_int const LAPACK_C_Decl::f_dbl_prec const LAPACK_C_Decl::f_int const LAPACK_C_Decl::f_int LAPACK_C_Decl::f_dbl_prec B[]
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
result = v_rhs1' * v_rhs2
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
bool TestMatrixSymSecant(const MatrixOp &B, const Vector &s, const Vector &y, value_type warning_tol, value_type error_tol, bool print_all_warnings, std::ostream *out, bool trase=true)
Checks the secant condition B*s = y.
void set_updated_stats(EUpdate update)
Initialize the statistics.
void V_VmV(VectorMutable *v_lhs, const V1 &V1_rhs1, const V2 &V2_rhs2)
v_lhs = V_rhs1 - V_rhs2.
void Vp_V(VectorMutable *v_lhs, const V &V_rhs)
v_lhs += V_rhs.