50 #include "NLPInterfacePack_NLPDirectTester.hpp"
51 #include "NLPInterfacePack_NLPDirect.hpp"
52 #include "AbstractLinAlgPack_VectorMutable.hpp"
53 #include "AbstractLinAlgPack_VectorOut.hpp"
54 #include "AbstractLinAlgPack_VectorSpace.hpp"
55 #include "AbstractLinAlgPack_VectorStdOps.hpp"
56 #include "AbstractLinAlgPack_LinAlgOpPack.hpp"
57 #include "AbstractLinAlgPack_LinAlgOpPack.hpp"
58 #include "AbstractLinAlgPack_assert_print_nan_inf.hpp"
59 #include "TestingHelperPack_update_success.hpp"
60 #include "Teuchos_Assert.hpp"
65 T my_max(
const T& v1,
const T& v2 ) {
return v1 > v2 ? v1 : v2; }
68 namespace NLPInterfacePack {
71 const calc_fd_prod_ptr_t &calc_fd_prod
74 ,value_type Gf_warning_tol
75 ,value_type Gf_error_tol
76 ,value_type Gc_warning_tol
77 ,value_type Gc_error_tol
81 :calc_fd_prod_(calc_fd_prod)
82 ,Gf_testing_method_(Gf_testing_method)
83 ,Gc_testing_method_(Gc_testing_method)
84 ,Gf_warning_tol_(Gf_warning_tol)
85 ,Gf_error_tol_(Gf_error_tol)
86 ,Gc_warning_tol_(Gc_warning_tol)
87 ,Gc_error_tol_(Gc_error_tol)
88 ,num_fd_directions_(num_fd_directions)
91 if(calc_fd_prod_ == Teuchos::null)
107 ,
bool print_all_warnings
120 using AbstractLinAlgPack::assert_print_nan_inf;
122 using LinAlgOpPack::V_StMtV;
123 using LinAlgOpPack::Vp_MtV;
125 using LinAlgOpPack::M_StMtM;
127 typedef VectorSpace::vec_mut_ptr_t vec_mut_ptr_t;
132 using TestingHelperPack::update_success;
134 bool success =
true, preformed_fd;
136 *out << std::boolalpha
138 <<
"*********************************************************\n"
139 <<
"*** NLPDirectTester::finite_diff_check(...) ***\n"
140 <<
"*********************************************************\n";
156 py && !c, std::invalid_argument
157 ,
"NLPDirectTester::finite_diff_check(...) : "
158 "Error, if py!=NULL then c!=NULL must also be true!" );
161 &fd_deriv_prod = this->calc_fd_prod();
164 rand_y_l = -1.0, rand_y_u = 1.0,
165 small_num = ::sqrt(std::numeric_limits<value_type>::epsilon());
173 switch( Gf_testing_method() ) {
174 case FD_COMPUTE_ALL: {
179 case FD_DIRECTIONAL: {
183 <<
"\nComparing products Gf'*y with finite difference values FDGf'*y for "
184 <<
"random y's ...\n";
185 vec_mut_ptr_t y = space_x->create_member();
186 value_type max_warning_viol = 0.0;
187 int num_warning_viol = 0;
188 const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
189 for(
int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
190 if( num_fd_directions() > 0 ) {
195 <<
"\n**** Random directional vector " << direc_i <<
" ( ||y||_1 / n = "
196 << (y->norm_1() / y->dim()) <<
" )"
204 <<
"\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<
" )"
208 Gf_y =
dot( *Gf, *y ),
212 ,*y,NULL,NULL,
true,nlp,&FDGf_y,NULL,out,dump_all(),dump_all()
215 goto FD_NOT_PREFORMED;
216 assert_print_nan_inf(FDGf_y,
"FDGf'*y",
true,out);
218 calc_err = ::fabs( ( Gf_y - FDGf_y )/( ::fabs(Gf_y) + ::fabs(FDGf_y) + small_num ) );
219 if( calc_err >= Gf_warning_tol() ) {
220 max_warning_viol = my_max( max_warning_viol, calc_err );
225 <<
"\nrel_err(Gf'*y,FDGf'*y) = "
226 <<
"rel_err(" << Gf_y <<
"," << FDGf_y <<
") = "
228 if( calc_err >= Gf_error_tol() ) {
231 <<
"Error, above relative error exceeded Gf_error_tol = " << Gf_error_tol() << endl;
233 *out <<
"\ny =\n" << *y;
238 if(out && num_warning_viol)
240 <<
"\nThere were " << num_warning_viol <<
" warning tolerance "
241 <<
"violations out of num_fd_directions = " << num_fd_directions()
242 <<
" computations of FDGf'*y\n"
243 <<
"and the maximum violation was " << max_warning_viol
244 <<
" > Gf_waring_tol = " << Gf_warning_tol() << endl;
276 <<
"\nComparing c with finite difference product FDA'*[ -py; 0 ] = -FDC*py ...\n";
278 VectorSpace::vec_mut_ptr_t
279 t1 = space_x->create_member();
280 V_StV( t1->sub_view(var_dep).get(), -1.0, *py );
281 *t1->sub_view(var_indep) = 0.0;
283 VectorSpace::vec_mut_ptr_t
284 t2 = nlp->
space_c()->create_member();
287 ,*t1,NULL,NULL,
true,nlp,NULL,t2.get(),out,dump_all(),dump_all()
290 goto FD_NOT_PREFORMED;
294 assert_print_nan_inf(sum_t2,
"sum(-FDC*py)",
true,out);
296 calc_err = ::fabs( ( sum_c - sum_t2 )/( ::fabs(sum_c) + ::fabs(sum_t2) + small_num ) );
299 <<
"\nrel_err(sum(c),sum(-FDC*py)) = "
300 <<
"rel_err(" << sum_c <<
"," << sum_t2 <<
") = "
302 if( calc_err >= Gc_error_tol() ) {
305 <<
"Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
306 if(print_all_warnings)
307 *out <<
"\nt1 = [ -py; 0 ] =\n" << *t1
308 <<
"\nt2 = FDA'*t1 = -FDC*py =\n" << *t2;
309 update_success(
false, &success );
311 if( calc_err >= Gc_warning_tol() ) {
314 <<
"\nWarning, above relative error exceeded Gc_warning_tol = " << Gc_warning_tol() << endl;
322 switch( Gc_testing_method() ) {
323 case FD_COMPUTE_ALL: {
376 case FD_DIRECTIONAL: {
395 <<
"\nComparing finite difference products -FDC*D*y with FDN*y for "
396 "random vectors y ...\n";
397 VectorSpace::vec_mut_ptr_t
398 y = space_x->sub_space(var_indep)->create_member(),
399 t1 = space_x->create_member(),
400 t2 = space_c->create_member(),
401 t3 = space_c->create_member();
402 value_type max_warning_viol = 0.0;
403 int num_warning_viol = 0;
404 const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
405 for(
int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
406 if( num_fd_directions() > 0 ) {
411 <<
"\n**** Random directional vector " << direc_i <<
" ( ||y||_1 / n = "
412 << (y->norm_1() / y->dim()) <<
" )"
420 <<
"\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<
" )"
424 *t1->sub_view(var_dep) = 0.0;
425 *t1->sub_view(var_indep) = *y;
429 ,*t1,NULL,NULL,
true,nlp,NULL,t2.get(),out,dump_all(),dump_all()
432 goto FD_NOT_PREFORMED;
435 *t1->sub_view(var_indep) = 0.0;
439 ,*t1,NULL,NULL,
true,nlp,NULL,t3.get(),out,dump_all(),dump_all()
446 calc_err = ::fabs( ( sum_t2 - sum_t3 )/( ::fabs(sum_t2) + ::fabs(sum_t3) + small_num ) );
449 <<
"\nrel_err(sum(-FDC*D*y),sum(FDN*y)) = "
450 <<
"rel_err(" << sum_t3 <<
"," << sum_t2 <<
") = "
452 if( calc_err >= Gc_warning_tol() ) {
453 max_warning_viol = my_max( max_warning_viol, calc_err );
456 if( calc_err >= Gc_error_tol() ) {
459 <<
"Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl
460 <<
"Stoping the tests!\n";
461 if(print_all_warnings)
462 *out <<
"\ny =\n" << *y
463 <<
"\nt1 = [ -D*y; 0 ] =\n" << *t1
464 <<
"\nt2 = FDA' * [ 0; y ] = FDN * y =\n" << *t2
465 <<
"\nt3 = FDA' * t1 = -FDC * D * y =\n" << *t3;
466 update_success(
false, &success );
469 if(out && num_warning_viol)
471 <<
"\nThere were " << num_warning_viol <<
" warning tolerance "
472 <<
"violations out of num_fd_directions = " << num_fd_directions()
473 <<
" computations of sum(FDC*D*y) and sum(FDN*y)\n"
474 <<
"and the maximum relative iolation was " << max_warning_viol
475 <<
" > Gc_waring_tol = " << Gc_warning_tol() << endl;
490 <<
"\nComparing rGf_tmp = Gf(var_indep) - D'*Gf(var_dep) with rGf ...\n";
491 VectorSpace::vec_mut_ptr_t
492 rGf_tmp = space_x->sub_space(var_indep)->create_member();
493 *rGf_tmp = *Gf->sub_view(var_indep);
496 sum_rGf_tmp =
sum(*rGf_tmp),
499 calc_err = ::fabs( ( sum_rGf_tmp - sum_rGf )/( ::fabs(sum_rGf_tmp) + ::fabs(sum_rGf) + small_num ) );
502 <<
"\nrel_err(sum(rGf_tmp),sum(rGf)) = "
503 <<
"rel_err(" << sum_rGf_tmp <<
"," << sum_rGf <<
") = "
505 if( calc_err >= Gc_error_tol() ) {
508 <<
"Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
509 if(print_all_warnings)
510 *out <<
"\nrGf_tmp =\n" << *rGf_tmp
511 <<
"\nrGf =\n" << *rGf;
512 update_success(
false, &success );
514 if( calc_err >= Gc_warning_tol() ) {
517 <<
"\nWarning, above relative error exceeded Gc_warning_tol = "
518 << Gc_warning_tol() << endl;
524 <<
"\nComparing rGf'*y with the finite difference product"
525 <<
" fd_prod(f,[D*y;y]) for random vectors y ...\n";
526 VectorSpace::vec_mut_ptr_t
527 y = space_x->sub_space(var_indep)->create_member(),
528 t = space_x->create_member();
529 value_type max_warning_viol = 0.0;
530 int num_warning_viol = 0;
531 const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 );
532 for(
int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) {
533 if( num_fd_directions() > 0 ) {
538 <<
"\n**** Random directional vector " << direc_i <<
" ( ||y||_1 / n = "
539 << (y->norm_1() / y->dim()) <<
" )"
547 <<
"\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<
" )"
552 *t->sub_view(var_indep) = *y;
553 value_type fd_rGf_y = 0.0;
557 ,*t,NULL,NULL,
true,nlp,&fd_rGf_y,NULL,out,dump_all(),dump_all()
560 goto FD_NOT_PREFORMED;
561 if(out) *out <<
"fd_prod(f,[D*y;y]) = " << fd_rGf_y <<
"\n";
563 const value_type rGf_y =
dot(*rGf,*y);
564 if(out) *out <<
"rGf'*y = " << rGf_y <<
"\n";
567 calc_err = ::fabs( ( rGf_y - fd_rGf_y )/( ::fabs(rGf_y) + ::fabs(fd_rGf_y) + small_num ) );
568 if( calc_err >= Gc_warning_tol() ) {
569 max_warning_viol = my_max( max_warning_viol, calc_err );
574 <<
"\nrel_err(rGf'*y,fd_prod(f,[D*y;y])) = "
575 <<
"rel_err(" << fd_rGf_y <<
"," << rGf_y <<
") = "
577 if( calc_err >= Gf_error_tol() ) {
579 *out <<
"Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl;
580 if(print_all_warnings)
581 *out <<
"\ny =\n" << *y
582 <<
"\nt = [ D*y; y ] =\n" << *t;
583 update_success(
false, &success );
604 <<
"\nError, the finite difference computation was not preformed due to cramped bounds\n"
605 <<
"Finite difference test failed!\n" << endl;
613 <<
"Error, found a NaN or Inf. Stoping tests\n";
620 <<
"\nCongradulations, all the finite difference errors where within the\n"
621 "specified error tolerances!\n";
624 <<
"\nOh no, at least one of the above finite difference tests failed!\n";
NLPDirectTester(const calc_fd_prod_ptr_t &calc_fd_prod=Teuchos::null, ETestingMethod Gf_testing_method=FD_DIRECTIONAL, ETestingMethod Gc_testing_method=FD_DIRECTIONAL, value_type Gf_warning_tol=1e-6, value_type Gf_error_tol=1e-1, value_type Gc_warning_tol=1e-6, value_type Gc_error_tol=1e-1, size_type num_fd_directions=1, bool dump_all=false)
Constructor.
virtual Range1D con_decomp() const
Return the range of decomposed equality constraints.
virtual vec_space_ptr_t space_x() const =0
Vector space object for unknown variables x (dimension n).
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void Vp_StV(VectorMutable *v_lhs, const value_type &alpha, const Vector &v_rhs)
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &V_rhs)
Interface providing only direct first order sensitivity information.
virtual Range1D con_undecomp() const
Return the range of undecomposed equality constraints.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool finite_diff_check(NLPDirect *nlp, const Vector &xo, const Vector *xl, const Vector *xu, const Vector *c, const Vector *Gf, const Vector *py, const Vector *rGf, const MatrixOp *GcU, const MatrixOp *D, const MatrixOp *Uz, bool print_all_warnings, std::ostream *out) const
This function takes an NLP object and its computed derivatives and function values and validates the ...
Strategy interface for computing the product of the derivatives of the functions of an NLP along give...
void M_StM(MatrixOp *M_lhs, value_type alpha, const MatrixOp &M_rhs, BLAS_Cpp::Transp trans_rhs)
virtual vec_space_ptr_t space_c() const =0
Vector space object for general equality constraints c(x) (dimension m).
virtual Range1D var_dep() const
Return the range of dependent (i.e. basic) variables.
virtual Range1D var_indep() const
Return the range of independent (i.e. nonbasic) variables.
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
virtual bool calc_deriv_product(const Vector &xo, const Vector *xl, const Vector *xu, const Vector &v, const value_type *fo, const Vector *co, bool check_nan_inf, NLP *nlp, value_type *Gf_prod, VectorMutable *Gc_prod, std::ostream *out, bool trace=false, bool dump_all=false) const
Compute the directional derivatives by finite differences.
value_type sum(const Vector &v_rhs)
void random_vector(value_type l, value_type u, VectorMutable *v)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)