MoochoPack : Framework for Large-Scale Optimization Algorithms  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MoochoPack_MoochoTrackerSummaryStd.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
5 // Copyright (2003) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #include <assert.h>
43 
44 #include <iomanip>
45 
46 #include "MoochoPack_MoochoTrackerSummaryStd.hpp"
47 #include "MoochoPack_NLPAlgoState.hpp"
48 #include "MoochoPack_moocho_algo_conversion.hpp"
49 #include "NLPInterfacePack_NLPFirstOrder.hpp"
50 #include "AbstractLinAlgPack_Vector.hpp"
51 #include "AbstractLinAlgPack_MatrixSymOp.hpp"
52 #include "Teuchos_dyn_cast.hpp"
53 
54 using std::endl;
55 using std::setw;
56 
57 namespace MoochoPack {
58 
59 MoochoTrackerSummaryStd::MoochoTrackerSummaryStd(
60  const ostream_ptr_t &o
61  ,const ostream_ptr_t &journal_out
62  ,EOptError opt_error
63  )
64  :AlgorithmTracker(journal_out)
65  ,o_(o)
66  ,opt_error_(opt_error)
67  ,num_total_qp_iter_(0)
68 {}
69 
71 {
72  o_ = o;
73 }
74 
77 {
78  return o_;
79 }
80 
82 {
83 
84  const NLPAlgo &_algo = rsqp_algo(algo);
85  const NLPAlgoState &s =_algo.rsqp_state();
86  const NLP &nlp = _algo.nlp();
87 
88  const size_type
89  m = nlp.m();
90 
91  std::ostream& o = this->o();
92 
93  int w = 15;
94  int prec = 6;
95  o.precision(prec);
96 
97  // Output the table's header for the first iteration
98  if(s.k() == 0) {
99  print_header(s);
100  }
101 
102  // ///////////////////////////////
103  // Output a row for the iteration
104 
105  // Get active set and QP solver statistics.
106  const ActSetStats *act_stats =
107  ( act_set_stats_.exists_in(s) && act_set_stats_(s).updated_k(0)
108  ? &act_set_stats_(s).get_k(0)
109  : NULL );
110  const QPSolverStats *qp_stats =
111  ( qp_solver_stats_.exists_in(s) && qp_solver_stats_(s).updated_k(0)
112  ? &qp_solver_stats_(s).get_k(0)
113  : NULL );
114  const QuasiNewtonStats *quasi_newt_stats =
115  ( quasi_newton_stats_.exists_in(s) && quasi_newton_stats_(s).updated_k(0)
116  ? &quasi_newton_stats_(s).get_k(0)
117  : NULL );
118 
119  // Get the norms of Ypy and Zpz
120  value_type norm_2_Ypy = -1.0, norm_2_Zpz = -1.0;
121  bool Ypy_exists, Zpz_exists;
122  if( m && ( Ypy_exists = s.Ypy().updated_k(0) ) )
123  norm_2_Ypy = s.Ypy().get_k(0).norm_2();
124  if( Zpz_exists = s.Zpz().updated_k(0) )
125  norm_2_Zpz = s.Zpz().get_k(0).norm_2();
126 
127  o << std::right
128  << setw(5) << s.k();
129 
130  if( s.f().updated_k(0) )
131  o << setw(w) << s.f().get_k(0);
132  else
133  o << setw(w) << "-";
134 
135  if( s.Gf().updated_k(0) )
136  o << setw(w) << s.Gf().get_k(0).norm_inf();
137  else
138  o << setw(w) << "-";
139 
140  if( m && s.c().updated_k(0) )
141  o << setw(w)
142  << s.c().get_k(0).norm_inf();
143  else
144  o << setw(w) << "-";
145 
146  {
147  const IterQuantityAccess<VectorMutable>
148  &rGL_GL = ( opt_error_ == OPT_ERROR_REDUCED_GRADIENT_LAGR
149  ? s.rGL() : s.GL() );
150  if( rGL_GL.updated_k(0) )
151  o << setw(w) << rGL_GL.get_k(0).norm_inf();
152  else
153  o << setw(w) << "-";
154  }
155 
156  if( quasi_newt_stats ) {
157  o << setw(w);
158  switch( quasi_newt_stats->updated() ) {
159  case QuasiNewtonStats::UNKNOWN:
160  o << "-";
161  break;
162  case QuasiNewtonStats:: REINITIALIZED:
163  o << "initialized";
164  break;
165  case QuasiNewtonStats::DAMPENED_UPDATED:
166  o << "damp.updated";
167  break;
168  case QuasiNewtonStats::UPDATED:
169  o << "updated";
170  break;
171  case QuasiNewtonStats::SKIPED:
172  o << "skiped";
173  break;
174  case QuasiNewtonStats::INDEF_SKIPED:
175  o << "indef skiped";
176  break;
177  default:
179  }
180  }
181  else {
182  o << setw(w) << "-";
183  }
184 
185  if( act_stats ) {
186  o << setw(7) << act_stats->num_active();
187  // don't know num_add and num_drops on first iteration.
188  if( act_stats->num_adds() == ActSetStats::NOT_KNOWN ) {
189  o << setw(7) << "-";
190  }
191  else {
192  o << setw(7) << act_stats->num_adds();
193  }
194  if( act_stats->num_drops() == ActSetStats::NOT_KNOWN ) {
195  o << setw(7) << "-";
196  }
197  else {
198  o << setw(7) << act_stats->num_drops();
199  }
200  }
201  else if( s.nu().updated_k(0) ) {
202  o << setw(7) << s.nu().get_k(0).nz()
203  << setw(7) << "-"
204  << setw(7) << "-";
205  }
206  else {
207  o << setw(7) << "-"
208  << setw(7) << "-"
209  << setw(7) << "-";
210  }
211 
212  if( qp_stats ) {
213  o << setw(7) << qp_stats->num_qp_iter()
214  << setw(3) << ( qp_stats->warm_start() ? 'w' : 'c')
215  << setw(2) << ( qp_stats->infeasible_qp() ? 'i' : 'f');
216  num_total_qp_iter_ += qp_stats->num_qp_iter();
217  }
218  else {
219  o << setw(7) << "-"
220  << setw(3) << "-"
221  << setw(2) << "-";
222  }
223 
224  if(m && Ypy_exists)
225  o << setw(w) << norm_2_Ypy;
226  else
227  o << setw(w) << "-";
228 
229  if(Zpz_exists)
230  o << setw(w) << norm_2_Zpz;
231  else
232  o << setw(w) << "-";
233 
234  if( s.d().updated_k(0) )
235  o << setw(w)
236  << s.d().get_k(0).norm_inf();
237  else
238  o << setw(w) << "-";
239 
240  if( s.alpha().updated_k(0) )
241  o << setw(w) << s.alpha().get_k(0);
242  else
243  o << setw(w) << "-";
244 
245  o << std::endl;
246 }
247 
249  , EAlgoReturn algo_return) const
250 {
251  using Teuchos::dyn_cast;
252 
253  const NLPAlgo &_algo = rsqp_algo(algo);
254  const NLPAlgoState &s =_algo.rsqp_state();
255  const NLPObjGrad &nlp = dyn_cast<const NLPObjGrad>(_algo.nlp());
256  const NLPFirstOrder *nlp_foi = dynamic_cast<const NLPFirstOrder*>(&nlp);
257 
258  const size_type
259  m = nlp.m();
260 
261  std::ostream& o = this->o();
262 
263  int w = 15;
264  int prec = 6;
265  o.precision(prec);
266 
267  // Get active set, QP solver and quasi-newton statistics.
268  const ActSetStats *act_stats =
269  ( act_set_stats_.exists_in(s) && act_set_stats_(s).updated_k(0)
270  ? &act_set_stats_(s).get_k(0)
271  : NULL );
272  const QPSolverStats *qp_stats =
273  ( qp_solver_stats_.exists_in(s) && qp_solver_stats_(s).updated_k(0)
274  ? &qp_solver_stats_(s).get_k(0)
275  : NULL );
276  const QuasiNewtonStats *quasi_newt_stats =
277  ( quasi_newton_stats_.exists_in(s) && quasi_newton_stats_(s).updated_k(0)
278  ? &quasi_newton_stats_(s).get_k(0)
279  : NULL );
280 
281  // Output the table's header for the first iteration
282  if(s.k() == 0) {
283  print_header(s);
284  }
285  else {
286  o << " ----"
287  << " ------------"
288  << " ------------"
289  << " ------------"
290  << " ------------"
291  << " ------------"
292  << " ------"
293  << " ------"
294  << " ------"
295  << " ------"
296  << " ----\n";
297  }
298 
299  o << std::right
300  << setw(5) << s.k();
301 
302  if( s.f().updated_k(0) )
303  o << setw(w) << s.f().get_k(0);
304  else
305  o << setw(w) << "-";
306 
307  if( s.Gf().updated_k(0) )
308  o << setw(w) << s.Gf().get_k(0).norm_inf();
309  else
310  o << setw(w) << "-";
311 
312  if( m && s.c().updated_k(0) )
313  o << setw(w)
314  << s.c().get_k(0).norm_inf();
315  else
316  o << setw(w) << "-";
317 
318  {
319  const IterQuantityAccess<VectorMutable>
320  &rGL_GL = ( opt_error_ == OPT_ERROR_REDUCED_GRADIENT_LAGR
321  ? s.rGL() : s.GL() );
322  if( rGL_GL.updated_k(0) )
323  o << setw(w) << rGL_GL.get_k(0).norm_inf();
324  else
325  o << setw(w) << "-";
326  }
327 
328  o << setw(w);
329  if( quasi_newt_stats ) {
330  switch( quasi_newt_stats->updated() ) {
331  case QuasiNewtonStats::UNKNOWN:
332  o << "-";
333  break;
334  case QuasiNewtonStats:: REINITIALIZED:
335  o << "initialized";
336  break;
337  case QuasiNewtonStats::DAMPENED_UPDATED:
338  o << "damp.updated";
339  break;
340  case QuasiNewtonStats::UPDATED:
341  o << "updated";
342  break;
343  case QuasiNewtonStats::SKIPED:
344  o << "skiped";
345  break;
346  case QuasiNewtonStats::INDEF_SKIPED:
347  o << "indef skiped";
348  break;
349  default:
351  }
352  }
353  else {
354  o << setw(w) << "-";;
355  }
356 
357  if( act_stats ) {
358  o << setw(7) << act_stats->num_active()
359  << setw(7) << act_stats->num_adds()
360  << setw(7) << act_stats->num_drops();
361  }
362  else if( s.nu().updated_k(0) ) {
363  o << setw(7) << s.nu().get_k(0).nz()
364  << setw(7) << "-"
365  << setw(7) << "-";
366  }
367  else {
368  o << setw(7) << "-"
369  << setw(7) << "-"
370  << setw(7) << "-";
371  }
372 
373  if( qp_stats ) {
374  o << setw(7) << qp_stats->num_qp_iter()
375  << setw(3) << ( qp_stats->warm_start() ? 'w' : 'c')
376  << setw(2) << ( qp_stats->infeasible_qp() ? 'i' : 'f');
377  num_total_qp_iter_ += qp_stats->num_qp_iter();
378  }
379  else {
380  o << setw(7) << "-"
381  << setw(3) << "-"
382  << setw(2) << "-";
383  }
384 
385  if(m && s.Ypy().updated_k(0))
386  o << setw(w)
387  << s.Ypy().get_k(0).norm_2();
388  else
389  o << setw(w) << "-";
390 
391  if(s.Zpz().updated_k(0))
392  o << setw(w)
393  << s.Zpz().get_k(0).norm_2();
394  else
395  o << setw(w) << "-";
396 
397  if( s.d().updated_k(0) )
398  o << setw(w)
399  << s.d().get_k(0).norm_inf();
400  else
401  o << setw(w) << "-";
402 
403  o << endl;
404 
405  o << "\nNumber of function evaluations:\n"
406  << "-------------------------------\n"
407  << "f(x) : " << nlp.num_f_evals() << endl
408  << "c(x) : " << ( m ? nlp.num_c_evals() : 0 ) << endl
409  << "Gf(x) : " << nlp.num_Gf_evals() << endl
410  << "Gc(x) : ";
411  if(m){
412  if( nlp_foi )
413  o << nlp_foi->num_Gc_evals();
414  else
415  o << "?";
416  }
417  else {
418  o << 0;
419  }
420  o << endl;
421 
422 }
423 
425 {
426  // Reset the count of total QP iterations
427  num_total_qp_iter_ = 0;
428 
429  std::ostream& o = this->o();
430 
431  NLPAlgoState::space_c_ptr_t
432  space_c = s.get_space_c();
433 
434  o << "\n\n********************************\n"
435  << "*** Start of rSQP Iterations ***\n"
436  << "n = " << s.space_x().dim()
437  << ", m = " << ( space_c.get() ? space_c->dim() : 0 )
438  << ", nz = ";
439  try {
440  if(space_c.get()) {
441  if( s.Gc().updated_k(0) )
442  o << s.Gc().get_k(0).nz() << endl;
443  else
444  o << "?\n";
445  }
446  else {
447  o << 0 << endl;
448  }
449  }
450  catch( const AlgorithmState::DoesNotExist& ) {
451  o << "?\n";
452  }
453  o
454  << "\n k "
455  << " f "
456  << " ||Gf||inf "
457  << " ||c||inf ";
458  switch(opt_error_) {
459  case OPT_ERROR_REDUCED_GRADIENT_LAGR:
460  o << " ||rGL||inf ";
461  break;
462  case OPT_ERROR_GRADIENT_LAGR:
463  o << " ||GL||inf ";
464  break;
465  default:
467  }
468  o << " quasi-Newton"
469  << " #act "
470  << " #adds "
471  << " #drops"
472  << " #qpitr"
473  << " wcfi "
474  << " ||Ypy||2 "
475  << " ||Zpz||2 "
476  << " ||d||inf "
477  << " alpha\n"
478  << " ----"
479  << " ------------"
480  << " ------------"
481  << " ------------"
482  << " ------------"
483  << " ------------"
484  << " ------"
485  << " ------"
486  << " ------"
487  << " ------"
488  << " ----"
489  << " ------------"
490  << " ------------"
491  << " ------------"
492  << " ------------\n";
493 }
494 
495 } // end namespace MoochoPack
void output_final(const Algorithm &algo, EAlgoReturn algo_return) const
Class for storing statistics about the Quasi-Newton updating.
void output_iteration(const Algorithm &algo) const
T_To & dyn_cast(T_From &from)
rSQP Algorithm control class.
Class for storing statistics about the changes in the active set of an SQP algorithm.
Reduced space SQP state encapsulation interface.
size_t size_type
NLPAlgoState & rsqp_state()
<<std aggr>="">> members for algo_cntr
void set_output_stream(const ostream_ptr_t &o)
Set the output stream for summary outputting.
const ostream_ptr_t & get_output_stream() const
Get the output stream for summary outputting.
void print_header(const NLPAlgoState &s) const
Print the header to the output.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)