MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MoochoPack_EvalNewPointTailoredApproach_Step.cpp
Go to the documentation of this file.
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 <ostream>
43 
56 #include "Teuchos_dyn_cast.hpp"
57 #include "Teuchos_Assert.hpp"
58 
59 namespace MoochoPack {
60 
62  const deriv_tester_ptr_t &deriv_tester
63  ,const bounds_tester_ptr_t &bounds_tester
64  , EFDDerivTesting fd_deriv_testing
65  )
66  :deriv_tester_(deriv_tester)
67  ,bounds_tester_(bounds_tester)
68  ,fd_deriv_testing_(fd_deriv_testing)
69 {}
70 
72  Algorithm& _algo, poss_type step_poss, IterationPack::EDoStepType type
73  ,poss_type assoc_step_poss
74  )
75 {
76 
77  using Teuchos::RCP;
78  using Teuchos::rcp;
79  using Teuchos::dyn_cast;
81  using LinAlgOpPack::V_MtV;
83 
84  NLPAlgo &algo = rsqp_algo(_algo);
85  NLPAlgoState &s = algo.rsqp_state();
86  NLPDirect &nlp = dyn_cast<NLPDirect>(algo.nlp());
87 
88  EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level();
89  EJournalOutputLevel ns_olevel = algo.algo_cntr().null_space_journal_output_level();
90  std::ostream& out = algo.track().journal_out();
91 
92  // print step header.
93  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
95  print_algorithm_step( algo, step_poss, type, assoc_step_poss, out );
96  }
97 
98  if(!nlp.is_initialized())
99  nlp.initialize(algo.algo_cntr().check_results());
100 
102  nlpOutputTempState(
103  rcp(&nlp,false), Teuchos::getFancyOStream(rcp(&out,false)),
104  convertToVerbLevel(olevel) );
105 
106  const Range1D
107  var_dep = nlp.var_dep(),
108  var_indep = nlp.var_indep();
109 
110  s.var_dep(var_dep);
111  s.var_indep(var_indep);
112 
113  const size_type
114  n = nlp.n(),
115  m = nlp.m(),
116  r = var_dep.size();
117 
119  m > r, TestFailed
120  ,"EvalNewPointTailoredApproach_Step::do_step(...) : Error, "
121  "Undecomposed equalities are supported yet!" );
122 
123  IterQuantityAccess<VectorMutable>
124  &x_iq = s.x();
125 
126  if( x_iq.last_updated() == IterQuantity::NONE_UPDATED ) {
127  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
128  out << "\nx is not updated for any k so set x_k = nlp.xinit() ...\n";
129  }
130  x_iq.set_k(0) = nlp.xinit();
131  }
132 
133  // Validate x
134  if(algo.algo_cntr().check_results()) {
136  x_iq.get_k(0), "x_k", true
137  , int(olevel) >= int(PRINT_ALGORITHM_STEPS) ? &out : NULL
138  );
139  if( nlp.num_bounded_x() > 0 ) {
140  if(!bounds_tester().check_in_bounds(
141  int(olevel) >= int(PRINT_ALGORITHM_STEPS) ? &out : NULL
142  ,int(olevel) >= int(PRINT_VECTORS) // print_all_warnings
143  ,int(olevel) >= int(PRINT_ITERATION_QUANTITIES) // print_vectors
144  ,nlp.xl(), "xl"
145  ,nlp.xu(), "xu"
146  ,x_iq.get_k(0), "x_k"
147  ))
148  {
150  true, TestFailed
151  ,"EvalNewPointTailoredApproach_Step::do_step(...) : Error, "
152  "the variables bounds xl <= x_k <= xu where violated!" );
153  }
154  }
155  }
156 
157  Vector &x = x_iq.get_k(0);
158 
159  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
160  out << "\n||x_k||inf = " << x.norm_inf();
161  if( var_dep.size() )
162  out << "\n||x(var_dep)_k||inf = " << x.sub_view(var_dep)->norm_inf();
163  if( var_indep.size() )
164  out << "\n||x(var_indep)_k||inf = " << x.sub_view(var_indep)->norm_inf();
165  out << std::endl;
166  }
167  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) {
168  out << "\nx_k = \n" << x;
169  if( var_dep.size() )
170  out << "\nx(var_dep)_k = \n" << *x.sub_view(var_dep);
171  }
172  if( static_cast<int>(ns_olevel) >= static_cast<int>(PRINT_VECTORS) ) {
173  if( var_indep.size() )
174  out << "\nx(var_indep)_k = \n" << *x.sub_view(var_indep);
175  }
176 
177  // If c_k is not updated then we must compute it
178  bool recalc_c = true;
179 
180  if( !s.c().updated_k(0) ) {
181  s.c().set_k(0);
182  recalc_c = true;
183  }
184  else {
185  recalc_c = false;
186  }
187 
188  // Get references to Z, Y, Uz and Uy
189  MatrixOp
190  &Z_k = s.Z().set_k(0),
191  &Y_k = s.Y().set_k(0),
192  *Uz_k = (m > r) ? &s.Uz().set_k(0) : NULL,
193  *Uy_k = (m > r) ? &s.Uy().set_k(0) : NULL;
194  MatrixIdentConcatStd
195  &cZ_k = dyn_cast<MatrixIdentConcatStd>(Z_k);
196  // Release any references to D in Y or Uy
197  uninitialize_Y_Uy(&Y_k,Uy_k);
198  // If Z has not been initialized or Z.D is being shared by someone else we need to reconstruct Z.D
199  bool reconstruct_Z_D = (cZ_k.rows() == n || cZ_k.cols() != n-r || cZ_k.D_ptr().total_count() > 1);
200  MatrixIdentConcatStd::D_ptr_t
201  D_ptr = Teuchos::null;
202  if( reconstruct_Z_D )
203  D_ptr = nlp.factory_D()->create();
204  else
205  D_ptr = cZ_k.D_ptr();
206 
207  // Compute all the quantities.
208  const bool supports_Gf = nlp.supports_Gf();
210  GcU = (m > r) ? nlp.factory_GcU()->create() : Teuchos::null; // ToDo: Reuse GcU somehow?
211  VectorMutable
212  &py_k = s.py().set_k(0);
213  nlp.unset_quantities();
214  nlp.calc_point(
215  x // x
216  ,!s.f().updated_k(0) ? &s.f().set_k(0) : NULL // f
217  ,&s.c().get_k(0) // c
218  ,recalc_c // recalc_c
219  ,supports_Gf?&s.Gf().set_k(0):NULL // Gf
220  ,&py_k // -inv(C)*c
221  ,&s.rGf().set_k(0) // rGf
222  ,GcU.get() // GcU
223  ,const_cast<MatrixOp*>(D_ptr.get()) // -inv(C)*N
224  ,Uz_k // Uz
225  );
226  s.equ_decomp( nlp.con_decomp() );
227  s.equ_undecomp( nlp.con_undecomp() );
228 
229  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
230  out << "\nQuantities computed directly from NLPDirect nlp object ...\n";
231  out << "\nf_k = " << s.f().get_k(0);
232  out << "\n||c_k||inf = " << s.c().get_k(0).norm_inf();
233  if(supports_Gf) {
234  const Vector &Gf = s.Gf().get_k(0);
235  out << "\n||Gf_k||inf = " << Gf.norm_inf();
236  if (var_dep.size())
237  out << "\n||Gf(var_dep)_k||inf = " << Gf.sub_view(var_dep)->norm_inf();
238  if (var_indep.size())
239  out << "\n||Gf(var_indep)_k||inf = " << Gf.sub_view(var_indep)->norm_inf();
240  }
241  out << "\n||py_k||inf = " << s.py().get_k(0).norm_inf();
242  out << "\n||rGf_k||inf = " << s.rGf().get_k(0).norm_inf();
243  out << std::endl;
244  }
245 
246  if( static_cast<int>(ns_olevel) >= static_cast<int>(PRINT_VECTORS) ) {
247  out << "\nrGf_k = \n" << s.rGf().get_k(0);
248  out << std::endl;
249  }
250 
251  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) {
252  out << "\nc_k = \n" << s.c().get_k(0);
253  if(supports_Gf)
254  out << "\nGf_k = \n" << s.Gf().get_k(0);
255  out << "\npy_k = \n" << s.py().get_k(0);
256  out << std::endl;
257  }
258 
259  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
260  out << "\nD = -inv(C)*N = \n" << *D_ptr;
261  out << std::endl;
262  }
263 
264  if( static_cast<int>(ns_olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
265  out << "Printing column norms of D = -inv(C)*N:\n";
267  e_i = D_ptr->space_rows().create_member();
269  D_i = D_ptr->space_cols().create_member();
270  *e_i = 0.0;
271  for( int i = 1; i <= (n-r); ++i ) {
272  e_i->set_ele(i,1.0);
273  V_MtV( &*D_i, *D_ptr, BLAS_Cpp::no_trans, *e_i );
274  e_i->set_ele(i,0.0);
275  out << " ||D(:,"<<i<<")||_2 = " << D_i->norm_2() << "\n";
276  }
277  }
278 
279  if(algo.algo_cntr().check_results()) {
280  assert_print_nan_inf(s.f().get_k(0), "f_k",true,&out);
281  assert_print_nan_inf(s.c().get_k(0), "c_k",true,&out);
282  if(supports_Gf)
283  assert_print_nan_inf(s.Gf().get_k(0), "Gf_k",true,&out);
284  assert_print_nan_inf(s.py().get_k(0), "py_k",true,&out);
285  assert_print_nan_inf(s.rGf().get_k(0), "rGf_k",true,&out);
286  }
287 
288  // Check the derivatives if we are checking the results
289  if( fd_deriv_testing() == FD_TEST
290  || ( fd_deriv_testing() == FD_DEFAULT && algo.algo_cntr().check_results() ) )
291  {
292 
293  if( olevel >= PRINT_ALGORITHM_STEPS ) {
294  out << "\n*** Checking derivatives by finite differences\n";
295  }
296 
297  const bool has_bounds = nlp.num_bounded_x() > 0;
298  const bool nlp_passed = deriv_tester().finite_diff_check(
299  &nlp
300  ,x
301  ,has_bounds ? &nlp.xl() : (const Vector*)NULL
302  ,has_bounds ? &nlp.xu() : (const Vector*)NULL
303  ,&s.c().get_k(0)
304  ,supports_Gf?&s.Gf().get_k(0):NULL
305  ,&s.py().get_k(0)
306  ,&s.rGf().get_k(0)
307  ,GcU.get()
308  ,D_ptr.get()
309  ,Uz_k
310  ,olevel >= PRINT_VECTORS
311  ,( olevel >= PRINT_ALGORITHM_STEPS ) ? &out : (std::ostream*)NULL
312  );
314  !nlp_passed, TestFailed
315  ,"EvalNewPointTailoredApproach_Step::do_step(...) : Error, "
316  "the tests of the nlp derivatives failed!" );
317  }
318 
319  if( reconstruct_Z_D ) {
320  //
321  // Z = [ D ] space_xD
322  // [ I ] space_xI
323  // space_xI
324  //
325  cZ_k.initialize(
326  nlp.space_x() // space_cols
327  ,nlp.space_x()->sub_space(nlp.var_indep())->clone() // space_rows
328  ,MatrixIdentConcatStd::TOP // top_or_bottom
329  ,1.0 // alpha
330  ,D_ptr // D_ptr
331  ,BLAS_Cpp::no_trans // D_trans
332  );
333  }
334 
335  // Compute py, Y and Uy
336  if( olevel >= PRINT_ALGORITHM_STEPS )
337  out << "\nUpdating py_k, Y_k, and Uy_k given D_k ...\n";
338  calc_py_Y_Uy( nlp, D_ptr, &py_k, &Y_k, Uy_k, olevel, out );
339 
340  // Compute Ypy = Y*py
341  VectorMutable
342  &Ypy_k = s.Ypy().set_k(0);
343  V_MtV( &Ypy_k, Y_k, BLAS_Cpp::no_trans, py_k );
344 
345  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
346  out << "\nQuantities after computing final py and Ypy ...\n";
347  out << "\n||py_k||inf = " << s.py().get_k(0).norm_inf();
348  out << "\n||Ypy_k||inf = " << s.Ypy().get_k(0).norm_inf();
349  out << std::endl;
350  }
351 
352  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) {
353  out << "\npy_k = \n" << s.py().get_k(0);
354  }
355 
356  if( static_cast<int>(ns_olevel) >= static_cast<int>(PRINT_VECTORS) ) {
357  if(var_indep.size())
358  out << "\nYpy(var_indep)_k = \n" << *s.Ypy().get_k(0).sub_view(var_indep);
359  out << std::endl;
360  }
361 
362  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) ) {
363  if(var_dep.size())
364  out << "\nYpy(var_dep)_k = \n" << *s.Ypy().get_k(0).sub_view(var_dep);
365  out << "\nYpy_k = \n" << s.Ypy().get_k(0);
366  out << std::endl;
367  }
368 
369  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ITERATION_QUANTITIES) ) {
370  out << "\nZ_k = \n" << s.Z().get_k(0);
371  out << "\nY_k = \n" << s.Y().get_k(0);
372  out << std::endl;
373  }
374 
375  return true;
376 
377 }
378 
380  const Algorithm& algo, poss_type step_poss, IterationPack::EDoStepType type
381  ,poss_type assoc_step_poss, std::ostream& out, const std::string& L
382  ) const
383 {
384  out
385  << L << "*** Evaluate the new point for the \"Tailored Approach\"\n"
386  << L << "if nlp is not initialized then initialize the nlp\n"
387  << L << "if x is not updated for any k then set x_k = nlp.xinit\n"
388  << L << "if Gf is supported then set Gf_k = Gf(x_k) <: space_x\n"
389  << L << "For Gc(:,equ_decomp) = [ C' ; N' ] <: space_x|space_c(equ_decomp) compute:\n"
390  << L << " py_k = -inv(C)*c_k\n"
391  << L << " D = -inv(C)*N <: R^(n x (n-m))\n"
392  << L << " rGf_k = D'*Gf_k(var_dep) + Gf_k(var_indep)\n"
393  << L << " Z_k = [ D ; I ] <: R^(n x (n-m))\n"
394  << L << " if m > r then\n"
395  << L << " Uz_k = Gc(var_indep,equ_undecomp)' + Gc(var_dep,equ_undecomp)'*D\n"
396  << L << " end\n"
397  << L << "if ( (fd_deriv_testing==FD_TEST)\n"
398  << L << " or (fd_deriv_testing==FD_DEFAULT and check_results==true)\n"
399  << L << " ) then\n"
400  << L << " check Gf_k, py_k, rGf_k, D, Uz (if m > r) and Vz (if mI > 0) by finite differences.\n"
401  << L << "end\n";
402  print_calc_py_Y_Uy( out, L );
403  out
404  << L << "Ypy_k = Y_k * py_k\n"
405  << L << "if c_k is not updated c_k = c(x_k) <: space_c\n"
406  << L << "if mI > 0 and h_k is not updated h_k = h(x_k) <: space_h\n"
407  << L << "if f_k is not updated f_k = f(x_k) <: REAL\n"
408  ;
409 }
410 
411 } // end namespace MoochoPack
AbstractLinAlgPack::size_type size_type
virtual void print_calc_py_Y_Uy(std::ostream &out, const std::string &leading_str) const =0
Overridden by subclass to print how py and Y are computed.
Thrown if a runtime test failed.
Teuchos::EVerbosityLevel convertToVerbLevel(const EJournalOutputLevel output_level)
Conver to Teuchos::EVerbosityLevel.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
rSQP Algorithm control class.
T * get() const
bool do_step(Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss)
void print_step(const Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss, std::ostream &out, const std::string &leading_str) const
Not transposed.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual std::ostream & journal_out() const
Return a reference to a std::ostream to be used to output debug information and the like...
EJournalOutputLevel
enum for journal output.
T_To & dyn_cast(T_From &from)
Reduced space SQP state encapsulation interface.
std::ostream * out
void print_algorithm_step(const Algorithm &algo, Algorithm::poss_type step_poss, EDoStepType type, Algorithm::poss_type assoc_step_poss, std::ostream &out)
Prints to 'out' the algorithm step.
AlgorithmTracker & track()
virtual void uninitialize_Y_Uy(MatrixOp *Y, MatrixOp *Uy)=0
Call to uninitialize the matrices.
bool assert_print_nan_inf(const value_type &val, const char name[], bool throw_excpt, std::ostream *out)
This function asserts if a value_type scalare is a NaN or Inf and optionally prints out these entires...
void V_MtV(VectorMutable *v_lhs, const MatrixOp &M_rhs1, BLAS_Cpp::Transp trans_rhs1, const V &V_rhs2)
v_lhs = op(M_rhs1) * V_rhs2.
Acts as the central hub for an iterative algorithm.
NLPAlgoState & rsqp_state()
<<std aggr>="">> members for algo_cntr
virtual void calc_py_Y_Uy(const NLPDirect &nlp, const D_ptr_t &D, VectorMutable *py, MatrixOp *Y, MatrixOp *Uy, EJournalOutputLevel olevel, std::ostream &out)=0
Overridden by subclass to compute py, Y and Uy.
int n
NLPAlgo & rsqp_algo(Algorithm &algo)
Convert from a Algorithm to a NLPAlgo.