MoochoPack : Framework for Large-Scale Optimization Algorithms Version of the Day
MoochoPack_MoochoTrackerSummaryStd.cpp
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00005 //                  Copyright (2003) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include <assert.h>
00043 
00044 #include <iomanip>
00045 
00046 #include "MoochoPack_MoochoTrackerSummaryStd.hpp"
00047 #include "MoochoPack_NLPAlgoState.hpp"
00048 #include "MoochoPack_moocho_algo_conversion.hpp"
00049 #include "NLPInterfacePack_NLPFirstOrder.hpp"
00050 #include "AbstractLinAlgPack_Vector.hpp"
00051 #include "AbstractLinAlgPack_MatrixSymOp.hpp"
00052 #include "Teuchos_dyn_cast.hpp"
00053 
00054 using std::endl;
00055 using std::setw;
00056 
00057 namespace MoochoPack {
00058 
00059 MoochoTrackerSummaryStd::MoochoTrackerSummaryStd(
00060   const ostream_ptr_t      &o
00061   ,const ostream_ptr_t     &journal_out
00062   ,EOptError               opt_error
00063   )
00064   :AlgorithmTracker(journal_out)
00065   ,o_(o)
00066   ,opt_error_(opt_error)
00067   ,num_total_qp_iter_(0)
00068 {}  
00069 
00070 void MoochoTrackerSummaryStd::set_output_stream(const ostream_ptr_t& o)
00071 { 
00072   o_ = o;
00073 }
00074 
00075 const MoochoTrackerSummaryStd::ostream_ptr_t&
00076 MoochoTrackerSummaryStd::get_output_stream() const
00077 {
00078   return o_;
00079 }
00080 
00081 void MoochoTrackerSummaryStd::output_iteration(const Algorithm& algo) const
00082 {
00083 
00084   const NLPAlgo            &_algo  = rsqp_algo(algo);
00085   const NLPAlgoState           &s      =_algo.rsqp_state();
00086   const NLP                 &nlp    = _algo.nlp(); 
00087 
00088   const size_type
00089     m = nlp.m();
00090 
00091   std::ostream& o = this->o();
00092   
00093   int w = 15;
00094   int prec = 6;
00095   o.precision(prec);
00096 
00097   // Output the table's header for the first iteration
00098   if(s.k() == 0) {
00099     print_header(s);
00100   }
00101 
00102   // ///////////////////////////////
00103   // Output a row for the iteration
00104   
00105   // Get active set and QP solver statistics.
00106   const ActSetStats   *act_stats =
00107     ( act_set_stats_.exists_in(s) && act_set_stats_(s).updated_k(0)
00108       ? &act_set_stats_(s).get_k(0)
00109       : NULL );
00110   const QPSolverStats   *qp_stats =
00111     ( qp_solver_stats_.exists_in(s) && qp_solver_stats_(s).updated_k(0)
00112       ? &qp_solver_stats_(s).get_k(0)
00113       : NULL );
00114   const QuasiNewtonStats  *quasi_newt_stats =
00115     ( quasi_newton_stats_.exists_in(s) && quasi_newton_stats_(s).updated_k(0)
00116       ? &quasi_newton_stats_(s).get_k(0)
00117       : NULL );
00118 
00119   // Get the norms of Ypy and Zpz
00120   value_type norm_2_Ypy = -1.0, norm_2_Zpz = -1.0;
00121   bool Ypy_exists, Zpz_exists;
00122   if( m && ( Ypy_exists = s.Ypy().updated_k(0) ) )
00123     norm_2_Ypy = s.Ypy().get_k(0).norm_2();
00124   if( Zpz_exists = s.Zpz().updated_k(0) )
00125     norm_2_Zpz = s.Zpz().get_k(0).norm_2();
00126 
00127   o << std::right
00128     << setw(5) << s.k();
00129 
00130   if( s.f().updated_k(0) )
00131     o << setw(w) << s.f().get_k(0);
00132   else
00133     o << setw(w) << "-";
00134 
00135   if( s.Gf().updated_k(0) )
00136     o << setw(w) << s.Gf().get_k(0).norm_inf();
00137   else
00138     o << setw(w) << "-";
00139 
00140   if( m && s.c().updated_k(0) )
00141     o << setw(w)
00142       << s.c().get_k(0).norm_inf();
00143   else
00144     o << setw(w) << "-";
00145 
00146   {
00147     const IterQuantityAccess<VectorMutable>
00148       &rGL_GL = ( opt_error_ == OPT_ERROR_REDUCED_GRADIENT_LAGR
00149               ? s.rGL() : s.GL()  );
00150     if( rGL_GL.updated_k(0) )
00151       o << setw(w) << rGL_GL.get_k(0).norm_inf();
00152     else
00153       o << setw(w) << "-";
00154   }
00155 
00156   if( quasi_newt_stats ) {
00157     o << setw(w);
00158     switch( quasi_newt_stats->updated() ) {
00159       case QuasiNewtonStats::UNKNOWN:
00160         o << "-";
00161         break;
00162       case QuasiNewtonStats:: REINITIALIZED:
00163         o << "initialized";
00164         break;
00165       case QuasiNewtonStats::DAMPENED_UPDATED:
00166         o << "damp.updated";
00167         break;
00168       case QuasiNewtonStats::UPDATED:
00169         o << "updated";
00170         break;
00171       case QuasiNewtonStats::SKIPED:
00172         o << "skiped";
00173         break;
00174       case QuasiNewtonStats::INDEF_SKIPED:
00175         o << "indef skiped";
00176         break;
00177       default:
00178         TEUCHOS_TEST_FOR_EXCEPT(true);
00179     }
00180   }
00181   else {
00182     o << setw(w) << "-";
00183   }
00184 
00185   if( act_stats ) {
00186     o << setw(7) << act_stats->num_active();
00187     // don't know num_add and num_drops on first iteration.
00188     if( act_stats->num_adds() == ActSetStats::NOT_KNOWN ) { 
00189       o << setw(7) << "-";
00190     }
00191     else {    
00192       o << setw(7) << act_stats->num_adds();
00193     }
00194     if( act_stats->num_drops() == ActSetStats::NOT_KNOWN ) {
00195       o << setw(7) << "-";
00196     }
00197     else {    
00198       o << setw(7) << act_stats->num_drops();
00199     }
00200   }
00201   else if( s.nu().updated_k(0) ) {
00202     o << setw(7) << s.nu().get_k(0).nz()
00203       << setw(7) << "-"
00204       << setw(7) << "-";
00205   }
00206   else {
00207     o << setw(7) << "-"
00208       << setw(7) << "-"
00209       << setw(7) << "-";
00210   }
00211 
00212   if( qp_stats ) {
00213     o << setw(7) << qp_stats->num_qp_iter()
00214       << setw(3) << ( qp_stats->warm_start() ? 'w' : 'c')
00215       << setw(2) << ( qp_stats->infeasible_qp() ? 'i' : 'f');
00216     num_total_qp_iter_ += qp_stats->num_qp_iter();
00217   }
00218   else {
00219   o << setw(7) << "-"
00220     << setw(3) << "-"
00221     << setw(2) << "-";
00222   }
00223 
00224   if(m && Ypy_exists)
00225     o << setw(w) << norm_2_Ypy;
00226   else
00227     o << setw(w) << "-";
00228 
00229   if(Zpz_exists)
00230     o << setw(w) << norm_2_Zpz;
00231   else
00232     o << setw(w) << "-";
00233 
00234   if( s.d().updated_k(0) )
00235     o << setw(w)
00236       << s.d().get_k(0).norm_inf();
00237   else
00238     o << setw(w) << "-";
00239 
00240   if( s.alpha().updated_k(0) )
00241     o << setw(w) << s.alpha().get_k(0);
00242   else
00243     o << setw(w) << "-";
00244 
00245   o << std::endl;
00246 }
00247 
00248 void MoochoTrackerSummaryStd::output_final(const Algorithm& algo
00249   , EAlgoReturn algo_return) const
00250 {
00251   using Teuchos::dyn_cast;
00252 
00253   const NLPAlgo            &_algo  = rsqp_algo(algo);
00254   const NLPAlgoState           &s      =_algo.rsqp_state();
00255   const NLPObjGrad      &nlp    = dyn_cast<const NLPObjGrad>(_algo.nlp()); 
00256   const NLPFirstOrder  *nlp_foi = dynamic_cast<const NLPFirstOrder*>(&nlp); 
00257 
00258   const size_type
00259     m = nlp.m();
00260 
00261   std::ostream& o = this->o();
00262 
00263   int w = 15;
00264   int prec = 6;
00265   o.precision(prec);
00266 
00267   // Get active set, QP solver and quasi-newton statistics.
00268   const ActSetStats   *act_stats =
00269     ( act_set_stats_.exists_in(s) && act_set_stats_(s).updated_k(0)
00270       ? &act_set_stats_(s).get_k(0)
00271       : NULL );
00272   const QPSolverStats   *qp_stats =
00273     ( qp_solver_stats_.exists_in(s) && qp_solver_stats_(s).updated_k(0)
00274       ? &qp_solver_stats_(s).get_k(0)
00275       : NULL );
00276   const QuasiNewtonStats  *quasi_newt_stats =
00277     ( quasi_newton_stats_.exists_in(s) && quasi_newton_stats_(s).updated_k(0)
00278       ? &quasi_newton_stats_(s).get_k(0)
00279       : NULL );
00280 
00281   // Output the table's header for the first iteration
00282   if(s.k() == 0) {
00283     print_header(s);
00284   }
00285   else {
00286     o << " ----"
00287       << "   ------------"
00288       << "   ------------"
00289       << "   ------------"
00290       << "   ------------"
00291       << "   ------------"
00292       << " ------"
00293       << " ------"
00294       << " ------"
00295       << " ------"
00296       << " ----\n";
00297   }
00298 
00299   o << std::right
00300     << setw(5) << s.k();
00301 
00302   if( s.f().updated_k(0) )
00303     o << setw(w) << s.f().get_k(0);
00304   else
00305     o << setw(w) << "-";
00306 
00307   if( s.Gf().updated_k(0) )
00308     o << setw(w) << s.Gf().get_k(0).norm_inf();
00309   else
00310     o << setw(w) << "-";
00311 
00312   if( m && s.c().updated_k(0) )
00313     o << setw(w)
00314       << s.c().get_k(0).norm_inf();
00315   else
00316     o << setw(w) << "-";
00317 
00318   {
00319     const IterQuantityAccess<VectorMutable>
00320       &rGL_GL = ( opt_error_ == OPT_ERROR_REDUCED_GRADIENT_LAGR
00321               ? s.rGL() : s.GL()  );
00322     if( rGL_GL.updated_k(0) )
00323       o << setw(w) << rGL_GL.get_k(0).norm_inf();
00324     else
00325       o << setw(w) << "-";
00326   }
00327 
00328   o << setw(w);
00329   if( quasi_newt_stats ) {
00330     switch( quasi_newt_stats->updated() ) {
00331       case QuasiNewtonStats::UNKNOWN:
00332         o << "-";
00333         break;
00334       case QuasiNewtonStats:: REINITIALIZED:
00335         o << "initialized";
00336         break;
00337       case QuasiNewtonStats::DAMPENED_UPDATED:
00338         o << "damp.updated";
00339         break;
00340       case QuasiNewtonStats::UPDATED:
00341         o << "updated";
00342         break;
00343       case QuasiNewtonStats::SKIPED:
00344         o << "skiped";
00345         break;
00346       case QuasiNewtonStats::INDEF_SKIPED:
00347         o << "indef skiped";
00348         break;
00349       default:
00350         TEUCHOS_TEST_FOR_EXCEPT(true);
00351     }
00352   }
00353   else {
00354     o << setw(w) << "-";;
00355   }
00356 
00357   if( act_stats ) {
00358     o << setw(7) << act_stats->num_active()
00359       << setw(7) << act_stats->num_adds()
00360       << setw(7) << act_stats->num_drops();
00361   }
00362   else if( s.nu().updated_k(0) ) {
00363     o << setw(7) << s.nu().get_k(0).nz()
00364       << setw(7) << "-"
00365       << setw(7) << "-";
00366   }
00367   else {
00368     o << setw(7) << "-"
00369       << setw(7) << "-"
00370       << setw(7) << "-";
00371   }
00372   
00373   if( qp_stats ) {
00374     o << setw(7) << qp_stats->num_qp_iter()
00375       << setw(3) << ( qp_stats->warm_start() ? 'w' : 'c')
00376       << setw(2) << ( qp_stats->infeasible_qp() ? 'i' : 'f');
00377     num_total_qp_iter_ += qp_stats->num_qp_iter();
00378   }
00379   else {
00380     o << setw(7) << "-"
00381       << setw(3) << "-"
00382       << setw(2) << "-";
00383   }
00384   
00385   if(m && s.Ypy().updated_k(0))
00386     o << setw(w) 
00387       << s.Ypy().get_k(0).norm_2();
00388   else
00389     o << setw(w) << "-";
00390   
00391   if(s.Zpz().updated_k(0))
00392     o << setw(w)
00393       << s.Zpz().get_k(0).norm_2();
00394   else
00395     o << setw(w) << "-";
00396   
00397   if( s.d().updated_k(0) )
00398     o << setw(w)
00399       << s.d().get_k(0).norm_inf();
00400   else
00401     o << setw(w) << "-";
00402 
00403   o << endl;
00404   
00405   o << "\nNumber of function evaluations:\n"
00406     <<     "-------------------------------\n"
00407     << "f(x)  : " << nlp.num_f_evals() << endl
00408     << "c(x)  : " << ( m ? nlp.num_c_evals() : 0 ) << endl
00409     << "Gf(x) : " << nlp.num_Gf_evals() << endl
00410     << "Gc(x) : ";
00411   if(m){
00412     if( nlp_foi )
00413       o << nlp_foi->num_Gc_evals();
00414     else
00415       o << "?";
00416   }
00417   else {
00418     o << 0;
00419   }
00420   o << endl;
00421 
00422 }
00423 
00424 void MoochoTrackerSummaryStd::print_header(const NLPAlgoState &s) const
00425 {
00426   // Reset the count of total QP iterations
00427   num_total_qp_iter_ = 0;
00428 
00429   std::ostream& o = this->o();
00430 
00431   NLPAlgoState::space_c_ptr_t
00432     space_c = s.get_space_c();
00433 
00434   o << "\n\n********************************\n"
00435     << "*** Start of rSQP Iterations ***\n"
00436     << "n = " << s.space_x().dim()
00437     << ", m = " << ( space_c.get() ? space_c->dim() : 0 )
00438     << ", nz = ";
00439   try {
00440     if(space_c.get()) {
00441       if( s.Gc().updated_k(0) )
00442         o << s.Gc().get_k(0).nz() << endl;
00443       else
00444         o << "?\n";
00445     }
00446     else {
00447       o << 0 << endl;
00448     }
00449   }
00450   catch( const AlgorithmState::DoesNotExist& ) {
00451       o << "?\n";
00452   }
00453   o
00454     << "\n k   "
00455     << "   f           "
00456     << "   ||Gf||inf   "
00457     << "   ||c||inf    ";
00458   switch(opt_error_) {
00459     case OPT_ERROR_REDUCED_GRADIENT_LAGR:
00460       o << "   ||rGL||inf  ";
00461       break;
00462     case OPT_ERROR_GRADIENT_LAGR:
00463       o << "   ||GL||inf  ";
00464       break;
00465     default:
00466       TEUCHOS_TEST_FOR_EXCEPT(true);
00467   }
00468   o   << "   quasi-Newton"
00469     << " #act  "
00470     << " #adds "
00471     << " #drops"
00472     << " #qpitr"
00473     << " wcfi  "
00474     << "   ||Ypy||2    "
00475     << "   ||Zpz||2    "
00476     << "   ||d||inf    "
00477     << "   alpha\n"
00478     << " ----"
00479     << "   ------------"
00480     << "   ------------"
00481     << "   ------------"
00482     << "   ------------"
00483     << "   ------------"
00484     << " ------"
00485     << " ------"
00486     << " ------"
00487     << " ------"
00488     << " ----"
00489     << "   ------------"
00490     << "   ------------"
00491     << "   ------------"
00492     << "   ------------\n";
00493 }
00494 
00495 } // end namespace MoochoPack
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends