bool MultiVectorMutableCols::syrk( BLAS_Cpp::Transp M_trans, value_type alpha , value_type beta, MatrixSymOp* sym_lhs ) const { using LinAlgOpPack::dot; MatrixSymOpGetGMSSymMutable *symwo_gms_lhs = dynamic_cast<MatrixSymOpGetGMSSymMutable*>(sym_lhs); if(!symwo_gms_lhs) { return MatrixOp::syrk(M_trans,alpha,beta,sym_lhs); // Boot it } MatrixDenseSymMutableEncap DMatrixSliceSym(symwo_gms_lhs); const int num_vecs = this->col_vecs_.size(); TEST_FOR_EXCEPTION( num_vecs != DMatrixSliceSym().rows(), std::logic_error ,"MultiVectorMutableCols::syrk(...) : Error, sizes do not match up!" ); // Fill the upper or lower triangular region. if( DMatrixSliceSym().uplo() == BLAS_Cpp::upper ) { for( int i = 1; i <= num_vecs; ++i ) { for( int j = i; j <= num_vecs; ++j ) { // Upper triangle! DMatrixSliceSym().gms()(i,j) = beta * DMatrixSliceSym().gms()(i,j) + alpha * dot(*col_vecs_[i-1],*col_vecs_[j-1]); } } } else { for( int i = 1; i <= num_vecs; ++i ) { for( int j = 1; j <= i; ++j ) { // Lower triangle! DMatrixSliceSym().gms()(i,j) = beta * DMatrixSliceSym().gms()(i,j) + alpha * dot(*col_vecs_[i-1],*col_vecs_[j-1]); } } } return true; }
void ExampleNLPObjGrad::imp_calc_f(const Vector& x, bool newx , const ZeroOrderInfo& zero_order_info) const { using AbstractLinAlgPack::dot; assert_is_initialized(); f(); // assert f is set TEUCHOS_TEST_FOR_EXCEPTION( n() != x.dim(), std::length_error, "ExampleNLPObjGrad::imp_calc_f(...)" ); // f(x) = (obj_scale/2) * sum( x(i)^2, for i = 1..n ) *zero_order_info.f = obj_scale_ / 2.0 * dot(x,x); }
void MultiVectorMutableCols::Vp_StMtV( VectorMutable* y, value_type a, BLAS_Cpp::Transp M_trans ,const SpVectorSlice& x, value_type b ) const { using AbstractLinAlgPack::dot; // y = b*y LinAlgOpPack::Vt_S(y,b); if( M_trans == BLAS_Cpp::no_trans ) { // // y += a*M*x // // => // // y += a * x(1) * M(:,1) + a * x(2) * M(:,2) + ... // SpVectorSlice::difference_type o = x.offset(); for( SpVectorSlice::const_iterator itr = x.begin(); itr != x.end(); ++itr ) { const size_type j = itr->index() + o; LinAlgOpPack::Vp_StV( y, a * itr->value(), *col_vecs_[j-1] ); } } else { // // y += a*M'*x // // => // // y(1) += a M(:,1)*x // y(2) += a M(:,2)*x // ... // for( size_type j = 1; j <= col_vecs_.size(); ++j ) y->set_ele( j ,y->get_ele(j) + a * dot(*col_vecs_[j-1],x) ); } }
void MultiVectorMutableCols::Vp_StMtV( VectorMutable* y, value_type a, BLAS_Cpp::Transp M_trans ,const Vector& x, value_type b ) const { using AbstractLinAlgPack::dot; // y = b*y LinAlgOpPack::Vt_S(y,b); if( M_trans == BLAS_Cpp::no_trans ) { // // y += a*M*x // // => // // y += a * x(1) * M(:,1) + a * x(2) * M(:,2) + ... // for( size_type j = 1; j <= col_vecs_.size(); ++j ) LinAlgOpPack::Vp_StV( y, a * x.get_ele(j), *col_vecs_[j-1] ); } else { // // y += a*M'*x // // => // // y(1) += a M(:,1)*x // y(2) += a M(:,2)*x // ... // for( size_type j = 1; j <= col_vecs_.size(); ++j ) y->set_ele( j ,y->get_ele(j) + a * dot(*col_vecs_[j-1],x) ); } }
bool CheckDescentQuasiNormalStep_Step::do_step( Algorithm& _algo, poss_type step_poss, IterationPack::EDoStepType type ,poss_type assoc_step_poss ) { using BLAS_Cpp::no_trans; using AbstractLinAlgPack::dot; using LinAlgOpPack::V_MtV; NLPAlgo &algo = rsqp_algo(_algo); NLPAlgoState &s = algo.rsqp_state(); NLP &nlp = algo.nlp(); const Range1D equ_decomp = s.equ_decomp(); EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level(); std::ostream& out = algo.track().journal_out(); // print step header. if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { using IterationPack::print_algorithm_step; print_algorithm_step( algo, step_poss, type, assoc_step_poss, out ); } const size_type nb = nlp.num_bounded_x(); // Get iteration quantities IterQuantityAccess<VectorMutable> &c_iq = s.c(), &Ypy_iq = s.Ypy(); const Vector::vec_ptr_t cd_k = c_iq.get_k(0).sub_view(equ_decomp); const Vector &Ypy_k = Ypy_iq.get_k(0); value_type descent_c = -1.0; if( s.get_iter_quant_id( Gc_name ) != AlgorithmState::DOES_NOT_EXIST ) { if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { out << "\nGc_k exists; compute descent_c = c_k(equ_decomp)'*Gc_k(:,equ_decomp)'*Ypy_k ...\n"; } const MatrixOp::mat_ptr_t Gcd_k = s.Gc().get_k(0).sub_view(Range1D(),equ_decomp); VectorSpace::vec_mut_ptr_t t = cd_k->space().create_member(); V_MtV( t.get(), *Gcd_k, BLAS_Cpp::trans, Ypy_k ); if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) { out << "\nGc_k(:,equ_decomp)'*Ypy_k =\n" << *t; } descent_c = dot( *cd_k, *t ); } else { if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { out << "\nGc_k does not exist; compute descent_c = c_k(equ_decomp)'*FDGc_k(:,equ_decomp)'*Ypy_k " << "using finite differences ...\n"; } VectorSpace::vec_mut_ptr_t t = nlp.space_c()->create_member(); calc_fd_prod().calc_deriv_product( s.x().get_k(0),nb?&nlp.xl():NULL,nb?&nlp.xu():NULL ,Ypy_k,NULL,&c_iq.get_k(0),true,&nlp ,NULL,t.get() ,static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ? &out : NULL ); if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) { out << "\nFDGc_k(:,equ_decomp)'*Ypy_k =\n" << *t->sub_view(equ_decomp); } descent_c = dot( *cd_k, *t->sub_view(equ_decomp) ); } if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { out << "\ndescent_c = " << descent_c << std::endl; } if( descent_c > 0.0 ) { // ToDo: add some allowance for > 0.0 for finite difference errors! if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) { out << "\nError, descent_c > 0.0; this is not a descent direction\n" << "Throw TestFailed and terminate the algorithm ...\n"; } TEST_FOR_EXCEPTION( true, TestFailed ,"CheckDescentQuasiNormalStep_Step::do_step(...) : Error, descent for the decomposed constraints " "with respect to the quasi-normal step c_k(equ_decomp)'*FDGc_k(:,equ_decomp)'*Ypy_k = " << descent_c << " > 0.0; This is not a descent direction!\n" ); } return true; }
bool MoochoPack::CalcDFromYPYZPZ_Step::do_step(Algorithm& _algo , poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss) { using Teuchos::implicit_cast; using AbstractLinAlgPack::dot; using LinAlgOpPack::V_VpV; NLPAlgo &algo = rsqp_algo(_algo); NLPAlgoState &s = algo.rsqp_state(); EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level(); EJournalOutputLevel ns_olevel = algo.algo_cntr().null_space_journal_output_level(); std::ostream& out = algo.track().journal_out(); // print step header. if( implicit_cast<int>(olevel) >= implicit_cast<int>(PRINT_ALGORITHM_STEPS) ) { using IterationPack::print_algorithm_step; print_algorithm_step( algo, step_poss, type, assoc_step_poss, out ); } // d = Ypy + Zpz VectorMutable &d_k = s.d().set_k(0); const Vector &Ypy_k = s.Ypy().get_k(0); const Vector &Zpz_k = s.Zpz().get_k(0); V_VpV( &d_k, Ypy_k, Zpz_k ); Range1D var_dep = s.var_dep(), var_indep = s.var_indep(); if( implicit_cast<int>(olevel) >= implicit_cast<int>(PRINT_ALGORITHM_STEPS) ) { const value_type very_small = std::numeric_limits<value_type>::min(); out << "\n(Ypy_k'*Zpz_k)/(||Ypy_k||2 * ||Zpz_k||2 + eps)\n" << " = ("<<dot(Ypy_k,Zpz_k)<<")/("<<Ypy_k.norm_2()<<" * "<<Zpz_k.norm_2()<<" + "<<very_small<<")\n" << " = " << dot(Ypy_k,Zpz_k) / ( Ypy_k.norm_2() * Zpz_k.norm_2() + very_small ) << "\n"; /* ConstrainedOptPack::print_vector_change_stats( s.x().get_k(0), "x", s.d().get_k(0), "d", out ); */ // ToDo: Replace the above with a reduction operator! } if( implicit_cast<int>(olevel) >= implicit_cast<int>(PRINT_ALGORITHM_STEPS) ) { out << "\n||d_k||inf = " << d_k.norm_inf(); if( var_dep.size() ) out << "\n||d(var_dep)_k||inf = " << d_k.sub_view(var_dep)->norm_inf(); if( var_indep.size() ) out << "\n||d(var_indep)_k||inf = " << d_k.sub_view(var_indep)->norm_inf(); out << std::endl; } if( implicit_cast<int>(olevel) >= implicit_cast<int>(PRINT_VECTORS) ) { out << "\nd_k = \n" << d_k; if( var_dep.size() ) out << "\nd(var_dep)_k = \n" << *d_k.sub_view(var_dep); } if( implicit_cast<int>(ns_olevel) >= implicit_cast<int>(PRINT_VECTORS) ) { if( var_indep.size() ) out << "\nd(var_indep)_k = \n" << *d_k.sub_view(var_indep); } return true; }
bool NLPDirectTester::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 { using std::setw; using std::endl; using std::right; using AbstractLinAlgPack::sum; using AbstractLinAlgPack::dot; using AbstractLinAlgPack::Vp_StV; using AbstractLinAlgPack::random_vector; using AbstractLinAlgPack::assert_print_nan_inf; using LinAlgOpPack::V_StV; using LinAlgOpPack::V_StMtV; using LinAlgOpPack::Vp_MtV; using LinAlgOpPack::M_StM; using LinAlgOpPack::M_StMtM; typedef VectorSpace::vec_mut_ptr_t vec_mut_ptr_t; // using AbstractLinAlgPack::TestingPack::CompareDenseVectors; // using AbstractLinAlgPack::TestingPack::CompareDenseSparseMatrices; using TestingHelperPack::update_success; bool success = true, preformed_fd; if(out) { *out << std::boolalpha << std::endl << "*********************************************************\n" << "*** NLPDirectTester::finite_diff_check(...) ***\n" << "*********************************************************\n"; } const Range1D var_dep = nlp->var_dep(), var_indep = nlp->var_indep(), con_decomp = nlp->con_decomp(), con_undecomp = nlp->con_undecomp(); NLP::vec_space_ptr_t space_x = nlp->space_x(), space_c = nlp->space_c(); // ////////////////////////////////////////////// // Validate the input TEST_FOR_EXCEPTION( py && !c, std::invalid_argument ,"NLPDirectTester::finite_diff_check(...) : " "Error, if py!=NULL then c!=NULL must also be true!" ); const CalcFiniteDiffProd &fd_deriv_prod = this->calc_fd_prod(); const value_type rand_y_l = -1.0, rand_y_u = 1.0, small_num = ::sqrt(std::numeric_limits<value_type>::epsilon()); try { // /////////////////////////////////////////////// // (1) Check Gf if(Gf) { switch( Gf_testing_method() ) { case FD_COMPUTE_ALL: { // Compute FDGf outright TEST_FOR_EXCEPT(true); // ToDo: update above! break; } case FD_DIRECTIONAL: { // Compute FDGF'*y using random y's if(out) *out << "\nComparing products Gf'*y with finite difference values FDGf'*y for " << "random y's ...\n"; vec_mut_ptr_t y = space_x->create_member(); value_type max_warning_viol = 0.0; int num_warning_viol = 0; const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 ); for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) { if( num_fd_directions() > 0 ) { random_vector( rand_y_l, rand_y_u, y.get() ); if(out) *out << "\n****" << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = " << (y->norm_1() / y->dim()) << " )" << "\n***\n"; } else { *y = 1.0; if(out) *out << "\n****" << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )" << "\n***\n"; } value_type Gf_y = dot( *Gf, *y ), FDGf_y; preformed_fd = fd_deriv_prod.calc_deriv_product( xo,xl,xu ,*y,NULL,NULL,true,nlp,&FDGf_y,NULL,out,dump_all(),dump_all() ); if( !preformed_fd ) goto FD_NOT_PREFORMED; assert_print_nan_inf(FDGf_y, "FDGf'*y",true,out); const value_type calc_err = ::fabs( ( Gf_y - FDGf_y )/( ::fabs(Gf_y) + ::fabs(FDGf_y) + small_num ) ); if( calc_err >= Gf_warning_tol() ) { max_warning_viol = my_max( max_warning_viol, calc_err ); ++num_warning_viol; } if(out) *out << "\nrel_err(Gf'*y,FDGf'*y) = " << "rel_err(" << Gf_y << "," << FDGf_y << ") = " << calc_err << endl; if( calc_err >= Gf_error_tol() ) { if(out) { *out << "Error, above relative error exceeded Gf_error_tol = " << Gf_error_tol() << endl; if(dump_all()) { *out << "\ny =\n" << *y; } } } } if(out && num_warning_viol) *out << "\nThere were " << num_warning_viol << " warning tolerance " << "violations out of num_fd_directions = " << num_fd_directions() << " computations of FDGf'*y\n" << "and the maximum violation was " << max_warning_viol << " > Gf_waring_tol = " << Gf_warning_tol() << endl; break; } default: TEST_FOR_EXCEPT(true); // Invalid value } } // ///////////////////////////////////////////// // (2) Check py = -inv(C)*c // // We want to check; // // FDC * (inv(C)*c) \approx c // \_________/ // -py // // We can compute this as: // // FDC * py = [ FDC, FDN ] * [ -py ; 0 ] // \__________/ // FDA' // // t1 = [ -py ; 0 ] // // t2 = FDA'*t1 // // Compare t2 \approx c // if(py) { if(out) *out << "\nComparing c with finite difference product FDA'*[ -py; 0 ] = -FDC*py ...\n"; // t1 = [ -py ; 0 ] VectorSpace::vec_mut_ptr_t t1 = space_x->create_member(); V_StV( t1->sub_view(var_dep).get(), -1.0, *py ); *t1->sub_view(var_indep) = 0.0; // t2 = FDA'*t1 VectorSpace::vec_mut_ptr_t t2 = nlp->space_c()->create_member(); preformed_fd = fd_deriv_prod.calc_deriv_product( xo,xl,xu ,*t1,NULL,NULL,true,nlp,NULL,t2.get(),out,dump_all(),dump_all() ); if( !preformed_fd ) goto FD_NOT_PREFORMED; const value_type sum_c = sum(*c), sum_t2 = sum(*t2); assert_print_nan_inf(sum_t2, "sum(-FDC*py)",true,out); const value_type calc_err = ::fabs( ( sum_c - sum_t2 )/( ::fabs(sum_c) + ::fabs(sum_t2) + small_num ) ); if(out) *out << "\nrel_err(sum(c),sum(-FDC*py)) = " << "rel_err(" << sum_c << "," << sum_t2 << ") = " << calc_err << endl; if( calc_err >= Gc_error_tol() ) { if(out) *out << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl; if(print_all_warnings) *out << "\nt1 = [ -py; 0 ] =\n" << *t1 << "\nt2 = FDA'*t1 = -FDC*py =\n" << *t2; update_success( false, &success ); } if( calc_err >= Gc_warning_tol() ) { if(out) *out << "\nWarning, above relative error exceeded Gc_warning_tol = " << Gc_warning_tol() << endl; } } // ///////////////////////////////////////////// // (3) Check D = -inv(C)*N if(D) { switch( Gc_testing_method() ) { case FD_COMPUTE_ALL: { // // Compute FDN outright and check // -FDC * D \aprox FDN // // We want to compute: // // FDC * -D = [ FDC, FDN ] * [ -D; 0 ] // \__________/ // FDA' // // To compute the above we perform: // // T = FDA' * [ -D; 0 ] (one column at a time) // // Compare T \approx FDN // /* // FDN DMatrix FDN(m,n-m); fd_deriv_computer.calc_deriv( xo, xl, xu , Range1D(m+1,n), nlp, NULL , &FDN() ,BLAS_Cpp::trans, out ); // T = FDA' * [ -D; 0 ] (one column at a time) DMatrix T(m,n-m); DVector t(n); t(m+1,n) = 0.0; for( int s = 1; s <= n-m; ++s ) { // t = [ -D(:,s); 0 ] V_StV( &t(1,m), -1.0, D->col(s) ); // T(:,s) = FDA' * t fd_deriv_prod.calc_deriv_product( xo,xl,xu,t(),NULL,NULL,nlp,NULL,&T.col(s),out); } // Compare T \approx FDN if(out) *out << "\nChecking the computed D = -inv(C)*N\n" << "where D(i,j) = (-FDC*D)(i,j), dM(i,j) = FDN(i,j) ...\n"; result = comp_M.comp( T(), FDN, BLAS_Cpp::no_trans , CompareDenseSparseMatrices::FULL_MATRIX , CompareDenseSparseMatrices::REL_ERR_BY_COL , Gc_warning_tol(), Gc_error_tol() , print_all_warnings, out ); update_success( result, &success ); if(!result) return false; */ TEST_FOR_EXCEPT(true); // Todo: Implement above! break; } case FD_DIRECTIONAL: { // // Compute -FDC * D * v \aprox FDN * v // for random v's // // We will compute this as: // // t1 = [ 0; y ] <: R^(n) // // t2 = FDA' * t1 ( FDN * y ) <: R^(m) // // t1 = [ -D * y ; 0 ] <: R^(n) // // t3 = FDA' * t1 ( -FDC * D * y ) <: R^(m) // // Compare t2 \approx t3 // if(out) *out << "\nComparing finite difference products -FDC*D*y with FDN*y for " "random vectors y ...\n"; VectorSpace::vec_mut_ptr_t y = space_x->sub_space(var_indep)->create_member(), t1 = space_x->create_member(), t2 = space_c->create_member(), t3 = space_c->create_member(); value_type max_warning_viol = 0.0; int num_warning_viol = 0; const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 ); for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) { if( num_fd_directions() > 0 ) { random_vector( rand_y_l, rand_y_u, y.get() ); if(out) *out << "\n****" << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = " << (y->norm_1() / y->dim()) << " )" << "\n***\n"; } else { *y = 1.0; if(out) *out << "\n****" << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )" << "\n***\n"; } // t1 = [ 0; y ] <: R^(n) *t1->sub_view(var_dep) = 0.0; *t1->sub_view(var_indep) = *y; // t2 = FDA' * t1 ( FDN * y ) <: R^(m) preformed_fd = fd_deriv_prod.calc_deriv_product( xo,xl,xu ,*t1,NULL,NULL,true,nlp,NULL,t2.get(),out,dump_all(),dump_all() ); if( !preformed_fd ) goto FD_NOT_PREFORMED; // t1 = [ -D * y ; 0 ] <: R^(n) V_StMtV( t1->sub_view(var_dep).get(), -1.0, *D, BLAS_Cpp::no_trans, *y ); *t1->sub_view(var_indep) = 0.0; // t3 = FDA' * t1 ( -FDC * D * y ) <: R^(m) preformed_fd = fd_deriv_prod.calc_deriv_product( xo,xl,xu ,*t1,NULL,NULL,true,nlp,NULL,t3.get(),out,dump_all(),dump_all() ); // Compare t2 \approx t3 const value_type sum_t2 = sum(*t2), sum_t3 = sum(*t3); const value_type calc_err = ::fabs( ( sum_t2 - sum_t3 )/( ::fabs(sum_t2) + ::fabs(sum_t3) + small_num ) ); if(out) *out << "\nrel_err(sum(-FDC*D*y),sum(FDN*y)) = " << "rel_err(" << sum_t3 << "," << sum_t2 << ") = " << calc_err << endl; if( calc_err >= Gc_warning_tol() ) { max_warning_viol = my_max( max_warning_viol, calc_err ); ++num_warning_viol; } if( calc_err >= Gc_error_tol() ) { if(out) *out << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl << "Stoping the tests!\n"; if(print_all_warnings) *out << "\ny =\n" << *y << "\nt1 = [ -D*y; 0 ] =\n" << *t1 << "\nt2 = FDA' * [ 0; y ] = FDN * y =\n" << *t2 << "\nt3 = FDA' * t1 = -FDC * D * y =\n" << *t3; update_success( false, &success ); } } if(out && num_warning_viol) *out << "\nThere were " << num_warning_viol << " warning tolerance " << "violations out of num_fd_directions = " << num_fd_directions() << " computations of sum(FDC*D*y) and sum(FDN*y)\n" << "and the maximum relative iolation was " << max_warning_viol << " > Gc_waring_tol = " << Gc_warning_tol() << endl; break; } default: TEST_FOR_EXCEPT(true); } } // /////////////////////////////////////////////// // (4) Check rGf = Gf(var_indep) + D'*Gf(var_dep) if(rGf) { if( Gf && D ) { if(out) *out << "\nComparing rGf_tmp = Gf(var_indep) - D'*Gf(var_dep) with rGf ...\n"; VectorSpace::vec_mut_ptr_t rGf_tmp = space_x->sub_space(var_indep)->create_member(); *rGf_tmp = *Gf->sub_view(var_indep); Vp_MtV( rGf_tmp.get(), *D, BLAS_Cpp::trans, *Gf->sub_view(var_dep) ); const value_type sum_rGf_tmp = sum(*rGf_tmp), sum_rGf = sum(*rGf); const value_type calc_err = ::fabs( ( sum_rGf_tmp - sum_rGf )/( ::fabs(sum_rGf_tmp) + ::fabs(sum_rGf) + small_num ) ); if(out) *out << "\nrel_err(sum(rGf_tmp),sum(rGf)) = " << "rel_err(" << sum_rGf_tmp << "," << sum_rGf << ") = " << calc_err << endl; if( calc_err >= Gc_error_tol() ) { if(out) *out << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl; if(print_all_warnings) *out << "\nrGf_tmp =\n" << *rGf_tmp << "\nrGf =\n" << *rGf; update_success( false, &success ); } if( calc_err >= Gc_warning_tol() ) { if(out) *out << "\nWarning, above relative error exceeded Gc_warning_tol = " << Gc_warning_tol() << endl; } } else if( D ) { if(out) *out << "\nComparing rGf'*y with the finite difference product" << " fd_prod(f,[D*y;y]) for random vectors y ...\n"; VectorSpace::vec_mut_ptr_t y = space_x->sub_space(var_indep)->create_member(), t = space_x->create_member(); value_type max_warning_viol = 0.0; int num_warning_viol = 0; const int num_fd_directions_used = ( num_fd_directions() > 0 ? num_fd_directions() : 1 ); for( int direc_i = 1; direc_i <= num_fd_directions_used; ++direc_i ) { if( num_fd_directions() > 0 ) { random_vector( rand_y_l, rand_y_u, y.get() ); if(out) *out << "\n****" << "\n**** Random directional vector " << direc_i << " ( ||y||_1 / n = " << (y->norm_1() / y->dim()) << " )" << "\n***\n"; } else { *y = 1.0; if(out) *out << "\n****" << "\n**** Ones vector y ( ||y||_1 / n = "<<(y->norm_1()/y->dim())<<" )" << "\n***\n"; } // t = [ D*y; y ] LinAlgOpPack::V_MtV(&*t->sub_view(var_dep),*D,BLAS_Cpp::no_trans,*y); *t->sub_view(var_indep) = *y; value_type fd_rGf_y = 0.0; // fd_Gf_y preformed_fd = fd_deriv_prod.calc_deriv_product( xo,xl,xu ,*t,NULL,NULL,true,nlp,&fd_rGf_y,NULL,out,dump_all(),dump_all() ); if( !preformed_fd ) goto FD_NOT_PREFORMED; if(out) *out << "fd_prod(f,[D*y;y]) = " << fd_rGf_y << "\n"; // rGf_y = rGf'*y const value_type rGf_y = dot(*rGf,*y); if(out) *out << "rGf'*y = " << rGf_y << "\n"; // Compare fd_rGf_y and rGf*y const value_type calc_err = ::fabs( ( rGf_y - fd_rGf_y )/( ::fabs(rGf_y) + ::fabs(fd_rGf_y) + small_num ) ); if( calc_err >= Gc_warning_tol() ) { max_warning_viol = my_max( max_warning_viol, calc_err ); ++num_warning_viol; } if(out) *out << "\nrel_err(rGf'*y,fd_prod(f,[D*y;y])) = " << "rel_err(" << fd_rGf_y << "," << rGf_y << ") = " << calc_err << endl; if( calc_err >= Gf_error_tol() ) { if(out) *out << "Error, above relative error exceeded Gc_error_tol = " << Gc_error_tol() << endl; if(print_all_warnings) *out << "\ny =\n" << *y << "\nt = [ D*y; y ] =\n" << *t; update_success( false, &success ); } } } else { TEST_FOR_EXCEPT(true); // ToDo: Test rGf without D? (This is not going to be easy!) } } // /////////////////////////////////////////////////// // (5) Check GcU, and/or Uz (for undecomposed equalities) if(GcU || Uz) { TEST_FOR_EXCEPT(true); // ToDo: Implement! } FD_NOT_PREFORMED: if(!preformed_fd) { if(out) *out << "\nError, the finite difference computation was not preformed due to cramped bounds\n" << "Finite difference test failed!\n" << endl; return false; } } // end try catch( const AbstractLinAlgPack::NaNInfException& except ) { if(out) *out << "Error, found a NaN or Inf. Stoping tests\n"; success = false; } if( out ) { if( success ) *out << "\nCongradulations, all the finite difference errors where within the\n" "specified error tolerances!\n"; else *out << "\nOh no, at least one of the above finite difference tests failed!\n"; } return success; }
void MatrixSymPosDefLBFGS::secant_update( VectorMutable* s, VectorMutable* y, VectorMutable* Bs ) { using AbstractLinAlgPack::BFGS_sTy_suff_p_d; using AbstractLinAlgPack::dot; using LinAlgOpPack::V_MtV; using Teuchos::Workspace; Teuchos::WorkspaceStore* wss = Teuchos::get_default_workspace_store().get(); assert_initialized(); // Check skipping the BFGS update const value_type sTy = dot(*s,*y); std::ostringstream omsg; if( !BFGS_sTy_suff_p_d(*s,*y,&sTy,&omsg,"MatrixSymPosDefLBFGS::secant_update(...)" ) ) { throw UpdateSkippedException( omsg.str() ); } try { // Update counters if( m_bar_ == m_ ) { // We are at the end of the storage so remove the oldest stored update // and move updates to make room for the new update. This has to be done for the // the matrix to behave properly {for( size_type k = 1; k <= m_-1; ++k ) { S_->col(k) = S_->col(k+1); // Shift S.col() to the left Y_->col(k) = Y_->col(k+1); // Shift Y.col() to the left STY_.col(k)(1,m_-1) = STY_.col(k+1)(2,m_); // Move submatrix STY(2,m-1,2,m-1) up and left STSYTY_.col(k)(k+1,m_) = STSYTY_.col(k+1)(k+2,m_+1); // Move triangular submatrix STS(2,m-1,2,m-1) up and left STSYTY_.col(k+1)(1,k) = STSYTY_.col(k+2)(2,k+1); // Move triangular submatrix YTY(2,m-1,2,m-1) up and left }} // ToDo: Create an abstract interface, call it MultiVectorShiftVecs, to rearrange S and Y all at once. // This will be important for parallel performance. } else { m_bar_++; } // Set the update vectors *S_->col(m_bar_) = *s; *Y_->col(m_bar_) = *y; // ///////////////////////////////////////////////////////////////////////////////////// // Update S'Y // // Update the row and column m_bar // // S'Y = // // [ s(1)'*y(1) ... s(1)'*y(m_bar) ... s(1)'*y(m_bar) ] // [ . . . ] row // [ s(m_bar)'*y(1) ... s(m_bar)'*y(m_bar) ... s(m_bar)'*y(m_bar) ] m_bar // [ . . . ] // [ s(m_bar)'*y(1) ... s(m_bar)'*y(m_bar) ... s(m_bar)'*y(m_bar) ] // // col m_bar // // Therefore we set: // (S'Y)(:,m_bar) = S'*y(m_bar) // (S'Y)(m_bar,:) = s(m_bar)'*Y const multi_vec_ptr_t S = this->S(), Y = this->Y(); VectorSpace::vec_mut_ptr_t t = S->space_rows().create_member(); // temporary workspace // (S'Y)(:,m_bar) = S'*y(m_bar) V_MtV( t.get(), *S, BLAS_Cpp::trans, *y ); STY_.col(m_bar_)(1,m_bar_) = VectorDenseEncap(*t)(); // (S'Y)(m_bar,:)' = Y'*s(m_bar) V_MtV( t.get(), *Y, BLAS_Cpp::trans, *s ); STY_.row(m_bar_)(1,m_bar_) = VectorDenseEncap(*t)(); // ///////////////////////////////////////////////////////////////// // Update S'S // // S'S = // // [ s(1)'*s(1) ... symmetric symmetric ] // [ . . . ] row // [ s(m_bar)'*s(1) ... s(m_bar)'*s(m_bar) ... symmetric ] m_bar // [ . . . ] // [ s(m_bar)'*s(1) ... s(m_bar)'*s(m_bar) ... s(m_bar)'*s(m_bar) ] // // col m_bar // // Here we will update the lower triangular part of S'S. To do this we // only need to compute: // t = S'*s(m_bar) = { s(m_bar)' * [ s(1),..,s(m_bar),..,s(m_bar) ] }' // then set the appropriate rows and columns of S'S. Workspace<value_type> work_ws(wss,m_bar_); DVectorSlice work(&work_ws[0],work_ws.size()); // work = S'*s(m_bar) V_MtV( t.get(), *S, BLAS_Cpp::trans, *s ); work = VectorDenseEncap(*t)(); // Set row elements STSYTY_.row(m_bar_+1)(1,m_bar_) = work; // Set column elements STSYTY_.col(m_bar_)(m_bar_+1,m_bar_+1) = work(m_bar_,m_bar_); // ///////////////////////////////////////////////////////////////////////////////////// // Update Y'Y // // Update the row and column m_bar // // Y'Y = // // [ y(1)'*y(1) ... y(1)'*y(m_bar) ... y(1)'*y(m_bar) ] // [ . . . ] row // [ symmetric ... y(m_bar)'*y(m_bar) ... y(m_bar)'*y(m_bar) ] m_bar // [ . . . ] // [ symmetric ... symmetric ... y(m_bar)'*y(m_bar) ] // // col m_bar // // Here we will update the upper triangular part of Y'Y. To do this we // only need to compute: // t = Y'*y(m_bar) = { y(m_bar)' * [ y(1),..,y(m_bar),..,y(m_bar) ] }' // then set the appropriate rows and columns of Y'Y. // work = Y'*y(m_bar) V_MtV( t.get(), *Y, BLAS_Cpp::trans, *y ); work = VectorDenseEncap(*t)(); // Set row elements STSYTY_.col(m_bar_+1)(1,m_bar_) = work; // Set column elements STSYTY_.row(m_bar_)(m_bar_+1,m_bar_+1) = work(m_bar_,m_bar_); // ///////////////////////////// // Update gamma_k // gamma_k = s'*y / y'*y if(auto_rescaling_) gamma_k_ = STY_(m_bar_,m_bar_) / STSYTY_(m_bar_,m_bar_+1); // We do not initially update Q unless we have to form a matrix-vector // product later. Q_updated_ = false; num_secant_updates_++; } // end try catch(...) { // If we throw any exception the we should make the matrix uninitialized // so that we do not leave this object in an inconsistant state. n_ = 0; throw; } }