44 #include "MoochoPack_BFGSUpdate_Strategy.hpp"
45 #include "MoochoPack_Exceptions.hpp"
46 #include "AbstractLinAlgPack_TestMatrixSymSecant.hpp"
47 #include "AbstractLinAlgPack_MatrixSymSecant.hpp"
48 #include "AbstractLinAlgPack_MatrixSymOp.hpp"
49 #include "AbstractLinAlgPack_MatrixOpOut.hpp"
50 #include "AbstractLinAlgPack_VectorSpace.hpp"
51 #include "AbstractLinAlgPack_VectorMutable.hpp"
52 #include "AbstractLinAlgPack_VectorOut.hpp"
53 #include "AbstractLinAlgPack_VectorStdOps.hpp"
54 #include "AbstractLinAlgPack_LinAlgOpPack.hpp"
55 #include "Teuchos_dyn_cast.hpp"
56 #include "Teuchos_Assert.hpp"
58 namespace MoochoPack {
61 bool rescale_init_identity
64 ,value_type secant_warning_tol
65 ,value_type secant_error_tol
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
79 ,EJournalOutputLevel olevel
85 namespace rcp = MemMngPack;
94 using LinAlgOpPack::V_MtV;
97 NOT_CALCULATED = std::numeric_limits<value_type>::max();
100 yTy = NOT_CALCULATED;
101 bool used_dampening =
false;
104 if( sTy == NOT_CALCULATED )
105 sTy =
dot( *s_bfgs, *y_bfgs );
107 if( (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS ) {
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 ) {
135 if( (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS ) {
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 );
141 if( (
int)olevel >= (int)PRINT_ITERATION_QUANTITIES ) {
142 out <<
"\nB after rescaling = \n" << *B;
146 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
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() ) {
159 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS )
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 );
171 const value_type sTBs =
dot( *s_bfgs, *Bs );
174 theta = ( sTy >= 0.2 * sTBs )
176 : (0.8 * sTBs ) / ( sTBs - sTy );
177 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS )
180 <<
"\ns_bfgs'*y_bfgs = " << sTy
181 << ( theta == 1.0 ?
" >= " :
" < " )
182 <<
" s_bfgs' * B * s_bfgs = " << sTBs << std::endl;
185 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS )
188 <<
"Perform the undamped update ...\n";
193 Vt_S( y_bfgs, theta );
194 Vp_StV( y_bfgs, (1.0-theta), *Bs );
196 if( (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS )
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;
205 if( (
int)olevel >= (
int)PRINT_VECTORS )
208 <<
"y_bfgs =\n" << *y_bfgs;
211 used_dampening =
true;
217 VectorSpace::vec_mut_ptr_t
218 s_bfgs_save = Teuchos::null,
219 y_bfgs_save = Teuchos::null;
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 ) {
233 if( (
int)olevel >= (int)PRINT_BASIC_ALGORITHM_INFO ) {
234 out <<
"\nThe factorization of B failed in a major way! Rethrow!\n";
238 catch(
const MatrixSymSecant::UpdateSkippedException& excpt ) {
239 if( (
int)olevel >= (int)PRINT_BASIC_ALGORITHM_INFO ) {
240 out << excpt.what() << std::endl
241 <<
"\nSkipping BFGS update. B = B ...\n";
244 QuasiNewtonStats::INDEF_SKIPED );
248 if( (
int)olevel >= (
int)PRINT_ITERATION_QUANTITIES ) {
249 out <<
"\nB after the BFGS update = \n" << *B;
252 if( ( check_results && secant_testing() == SECANT_TEST_DEFAULT )
253 || secant_testing() == SECANT_TEST_ALWAYS )
256 AbstractLinAlgPack::TestMatrixSymSecant(
257 *B, *s_bfgs_save, *y_bfgs_save
258 , secant_warning_tol(), secant_error_tol()
259 , (
int)olevel >= (
int)PRINT_VECTORS
260 , (
int)olevel > (
int)PRINT_NOTHING ? &out : NULL
261 , (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS
265 msg[] =
"Error, the secant property for the BFGS update failed\n"
266 "Stopping the algorithm ...\n";
270 ,
" BFGSUpdate_Strategy::perform_update(...) : " << msg );
276 ? QuasiNewtonStats::DAMPENED_UPDATED
277 : QuasiNewtonStats::UPDATED );
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)
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)
T_To & dyn_cast(T_From &from)
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &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)
void V_VpV(VectorMutable *v_lhs, const V1 &V1_rhs1, const V2 &V2_rhs2)
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
void set_updated_stats(EUpdate update)
Initialize the statistics.
void V_VmV(VectorMutable *v_lhs, const V1 &V1_rhs1, const V2 &V2_rhs2)
void Vp_V(VectorMutable *v_lhs, const V &V_rhs)