50 #include "NLPInterfacePack_CalcFiniteDiffProd.hpp"
51 #include "NLPInterfacePack_NLP.hpp"
52 #include "AbstractLinAlgPack_VectorSpace.hpp"
53 #include "AbstractLinAlgPack_VectorOut.hpp"
54 #include "AbstractLinAlgPack_VectorMutable.hpp"
55 #include "AbstractLinAlgPack_LinAlgOpPack.hpp"
56 #include "AbstractLinAlgPack_assert_print_nan_inf.hpp"
57 #include "AbstractLinAlgPack_VectorAuxiliaryOps.hpp"
58 #include "Teuchos_FancyOStream.hpp"
59 #include "Teuchos_Assert.hpp"
61 namespace NLPInterfacePack {
66 ,value_type fd_step_size
67 ,value_type fd_step_size_min
68 ,value_type fd_step_size_f
69 ,value_type fd_step_size_c
71 :fd_method_order_(fd_method_order)
72 ,fd_step_select_(fd_step_select)
73 ,fd_step_size_(fd_step_size)
74 ,fd_step_size_min_(fd_step_size_min)
75 ,fd_step_size_f_(fd_step_size_f)
76 ,fd_step_size_c_(fd_step_size_c)
89 ,VectorMutable *Gc_prod
90 ,std::ostream *out_arg
103 typedef VectorSpace::vec_mut_ptr_t vec_mut_ptr_t;
107 using AbstractLinAlgPack::assert_print_nan_inf;
111 out = Teuchos::getFancyOStream(
Teuchos::rcp(out_arg,
false));
171 m==0 && Gc_prod, std::invalid_argument
172 ,
"CalcFiniteDiffProd::calc_deriv(...) : "
173 "Error, if nlp->m() == 0, then Gc_prod must equal NULL" );
175 Gc_prod && !Gc_prod->space().is_compatible(*nlp->space_c())
176 ,std::invalid_argument
177 ,
"CalcFiniteDiffProd::calc_deriv(...) : "
178 "Error, Gc_prod (type \' "<<
typeName(*Gc_prod)<<
"\' "
179 "is not compatible with the NLP" );
181 (xl && !xu) || (!xl && xu), std::invalid_argument
182 ,
"CalcFiniteDiffProd::calc_deriv(...) : "
183 "Error, both xl = "<<xl<<
" and xu = "<<xu
184 <<
" must be NULL or not NULL" );
186 assert_print_nan_inf(xo,
"xo",
true,out.
get());
188 switch(this->fd_method_order()) {
190 if(out.
get()&&trace) *out<<
"\nUsing one-sided, first-order finite differences ...\n";
193 if(out.
get()&&trace) *out<<
"\nUsing one-sided, second-order finite differences ...\n";
196 if(out.
get()&&trace) *out<<
"\nUsing second-order central finite differences ...\n";
199 if(out.
get()&&trace) *out<<
"\nUsing auto selection of some second-order finite difference method ...\n";
202 if(out.
get()&&trace) *out<<
"\nUsing one-sided, fourth-order finite differences ...\n";
205 if(out.
get()&&trace) *out<<
"\nUsing fourth-order central finite differences ...\n";
208 if(out.
get()&&trace) *out<<
"\nUsing auto selection of some fourth-order finite difference method ...\n";
222 sqrt_epsilon = ::pow(std::numeric_limits<value_type>::epsilon(),1.0/2.0),
223 u_optimal_1 = sqrt_epsilon,
224 u_optimal_2 = ::pow(sqrt_epsilon,1.0/2.0),
225 u_optimal_4 = ::pow(sqrt_epsilon,1.0/4.0),
226 xo_norm_inf = xo.norm_inf();
230 switch(this->fd_method_order()) {
232 uh_opt = u_optimal_1 * ( fd_step_select() ==
FD_STEP_ABSOLUTE ? 1.0 : xo_norm_inf + 1.0 );
237 uh_opt = u_optimal_2 * ( fd_step_select() ==
FD_STEP_ABSOLUTE ? 1.0 : xo_norm_inf + 1.0 );
242 uh_opt = u_optimal_4 * ( fd_step_select() ==
FD_STEP_ABSOLUTE ? 1.0 : xo_norm_inf + 1.0 );
248 if(out.
get()&&trace) *out<<
"\nDefault optimal step length uh_opt = " << uh_opt <<
" ...\n";
255 uh = this->fd_step_size(),
256 uh_f = this->fd_step_size_f(),
257 uh_c = this->fd_step_size_c(),
258 uh_min = this->fd_step_size_min();
264 uh *= (xo_norm_inf + 1.0);
269 uh_f *= (xo_norm_inf + 1.0);
274 uh_c *= (xo_norm_inf + 1.0);
276 if(out.
get()&&trace) *out<<
"\nIndividual step sizes initally set: uh="<<uh<<
",uh_f="<<uh_f<<
",uh_c="<<uh_c<<
"\n";
285 value_type max_u_feas = std::numeric_limits<value_type>::max();
287 std::pair<value_type,value_type>
296 if( u_pn.first < -u_pn.second )
297 max_u_feas = u_pn.first;
299 max_u_feas = u_pn.second;
300 const value_type abs_max_u_feas = ::fabs(max_u_feas);
301 if( abs_max_u_feas < uh ) {
302 if( abs_max_u_feas < uh_min ) {
305 <<
"Warning, the size of the maximum finite difference step length\n"
306 <<
"that does not violate the relaxed variable bounds uh = "
307 << max_u_feas <<
" is less than the mimimum allowable step length\n"
308 <<
"uh_min = " << uh_min <<
" and the finite difference "
309 <<
"derivatives are not computed!\n";
314 <<
"Warning, the size of the maximum finite difference step length\n"
315 <<
"that does not violate the relaxed variable bounds uh = "
316 << max_u_feas <<
" is less than the desired step length\n"
317 <<
"uh = " << uh <<
" and the finite difference "
318 <<
"derivatives may be much less accurate!\n";
329 switch(fd_method_order) {
340 abs_max_u_feas = ::fabs(max_u_feas);
343 switch(fd_method_order) {
363 uh = ( abs_max_u_feas/num_u_i < uh ? max_u_feas/num_u_i : uh );
364 uh_f = ( abs_max_u_feas/num_u_i < uh_f ? max_u_feas/num_u_i : uh_f );
365 uh_c = ( abs_max_u_feas/num_u_i < uh_c ? max_u_feas/num_u_i : uh_c );
371 if(out.
get()&&trace) *out<<
"\nIndividual step sizes to fit in bounds: uh="<<uh<<
",uh_f="<<uh_f<<
",uh_c="<<uh_c<<
"\n";
377 value_type *f_saved = NULL;
378 VectorMutable *c_saved = NULL;
380 f_saved = nlp->
get_f();
381 if(m) c_saved = nlp->
get_c();
385 p_saved = out->precision();
397 c = m && Gc_prod ? nlp->space_c()->
create_member() : Teuchos::null;
402 if(m) nlp->
set_c( c.get() );
404 const int dbl_p = 15;
406 *out << std::setprecision(dbl_p);
413 value_type dwgt = 0.0;
414 switch(fd_method_order) {
438 if(Gc_prod) *Gc_prod = 0.0;
439 if(Gf_prod) *Gf_prod = 0.0;
440 for(
int eval_i = 1; eval_i <= num_evals; ++eval_i ) {
445 switch(fd_method_order) {
537 if(out.
get()&&dump_all) {
538 *out<<
"\nxo =\n" << xo;
539 *out<<
"\nv =\n" << v;
540 if(fo) *out <<
"\nfo = " << *fo <<
"\n";
541 if(co) *out <<
"\nco =\n" << *co;
544 bool new_point =
true;
546 if( co && uh_i == 0.0 ) {
547 if(out.
get()&&trace) *out<<
"\nBase c = co ...\n";
551 if( new_point || uh_c != uh ) {
552 *x = xo;
Vp_StV( x.get(), uh_i * uh_c, v );
554 if(out.
get()&&trace) *out<<
"\nComputing c = c(xo+"<<(uh_i*uh_c)<<
"*v) ...\n";
555 if(out.
get()&&dump_all) *out<<
"\nxo+"<<(uh_i*uh_c)<<
"*v =\n" << *x;
556 nlp->
calc_c(*x,new_point);
559 if(out.
get() && dump_all) *out <<
"\nc =\n" << *c;
561 assert_print_nan_inf(*c,
"c(xo+u*v)",
true,out.
get());
562 if(out.
get()&&trace) *out<<
"\nGc_prod += "<<wgt_i<<
"*c ...\n";
563 Vp_StV( Gc_prod, wgt_i, *c );
564 if(out.
get() && dump_all) *out<<
"\nGc_prod =\n" << *Gc_prod;
568 if( fo && uh_i == 0.0 ) {
569 if(out.
get()&&trace) *out<<
"\nBase f = fo ...\n";
573 if( new_point || uh_f != uh ) {
574 *x = xo;
Vp_StV( x.get(), uh_i * uh_f, v );
577 if(out.
get()&&trace) *out<<
"\nComputing f = f(xo+"<<(uh_i*uh_f)<<
"*v) ...\n";
578 if(out.
get() && dump_all) *out<<
"\nxo+"<<(uh_i*uh_f)<<
"*v =\n" << *x;
579 nlp->
calc_f(*x,new_point);
582 if(out.
get() && dump_all) *out<<
"\nf = " << f <<
"\n";
584 assert_print_nan_inf(f,
"f(xo+u*v)",
true,out.
get());
585 if(out.
get()&&trace) *out<<
"\nGf_prod += "<<wgt_i<<
"*f ...\n";
586 *Gf_prod += wgt_i * f;
587 if(out.
get() && dump_all) *out<<
"\nGf_prod = " << *Gf_prod <<
"\n";
597 if(out.
get()&&trace) *out<<
"\nGc_prod *= "<<(1.0 / (dwgt * uh_c))<<
" ...\n";
598 Vt_S( Gc_prod, 1.0 / (dwgt * uh_c) );
599 if(out.
get() && dump_all)
600 *out<<
"\nFinal Gc_prod =\n" << *Gc_prod;
604 if(out.
get()&&trace) *out<<
"\nGf_prod *= "<<(1.0 / (dwgt * uh_f))<<
" ...\n";
605 *Gf_prod *= ( 1.0 / (dwgt * uh_f) );
606 if(out.
get() && dump_all)
607 *out<<
"\nFinal Gf_prod = " << *Gf_prod <<
"\n";
612 nlp->
set_f( f_saved );
613 if(m) nlp->
set_c( c_saved );
615 *out << std::setprecision(p_saved);
619 nlp->
set_f( f_saved );
620 if(m) nlp->
set_c( c_saved );
622 *out << std::setprecision(p_saved);
Use FD_ORDER_FOUR_CENTRAL when not limited by bounds, otherwise use FD_ORDER_FOUR.
virtual void calc_c(const Vector &x, bool newx=true) const
Update the constraint residual vector for c at the point x and put it in the stored reference...
CalcFiniteDiffProd(EFDMethodOrder fd_method_order=FD_ORDER_FOUR_AUTO, EFDStepSelect fd_step_select=FD_STEP_ABSOLUTE, value_type fd_step_size=-1.0, value_type fd_step_size_min=-1.0, value_type fd_step_size_f=-1.0, value_type fd_step_size_c=-1.0)
Use absolute step size fd_step_size
void Vt_S(VectorMutable *v_lhs, const value_type &alpha)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void Vp_StV(VectorMutable *v_lhs, const value_type &alpha, const Vector &v_rhs)
size_type rows(size_type rows, size_type cols, BLAS_Cpp::Transp _trans)
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &V_rhs)
Use O(eps^4) two sided central finite differences.
Use O(eps^2) one sided finite differences (cramped bounds)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void calc_f(const Vector &x, bool newx=true) const
Update the value for the objective f at the point x and put it in the stored reference.
virtual size_type n() const
Return the number of variables.
Use O(eps^2) two sided central finite differences.
virtual void set_c(VectorMutable *c)
Set a pointer to a vector to be updated when this->calc_c() is called.
virtual value_type * get_f()
Return pointer passed to this->set_f().
NLP interface class {abstract}.
virtual value_type max_var_bounds_viol() const =0
Set the maximum absolute value for which the variable bounds may be violated by when computing functi...
Use relative step size fd_step_size * ||xo||inf
std::pair< value_type, value_type > max_near_feas_step(const Vector &x, const Vector &d, const Vector &xl, const Vector &xu, value_type max_bnd_viol)
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.
Use FD_ORDER_TWO_CENTRAL when not limited by bounds, otherwise use FD_ORDER_TWO.
Use O(eps^4) one sided finite differences (cramped bounds)
virtual vec_mut_ptr_t create_member() const =0
virtual size_type m() const
Return the number of general equality constraints.
virtual VectorMutable * get_c()
Return pointer passed to this->set_c().
size_type cols(size_type rows, size_type cols, BLAS_Cpp::Transp _trans)
Use O(eps) one sided finite differences (cramped bounds)
virtual void set_f(value_type *f)
Set a pointer to an value to be updated when this->calc_f() is called.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
std::string typeName(const T &t)