MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MoochoPack_LineSearchFilter_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 <math.h>
43 
44 #include <ostream>
45 #include <fstream>
46 #include <typeinfo>
47 
57 #include "Teuchos_dyn_cast.hpp"
58 #include "Teuchos_Assert.hpp"
59 #include "Teuchos_as.hpp"
60 
61 //#define FILTER_DEBUG_OUT 1
62 
63 
64 namespace {
65 
66 
67 class RemoveFilterEntryPred {
68 public:
69 
70  RemoveFilterEntryPred(
71  const MoochoPack::value_type &f_with_boundary,
72  const MoochoPack::value_type &theta_with_boundary,
74  )
75  :f_with_boundary_(f_with_boundary),
76  theta_with_boundary_(theta_with_boundary),
77  out_(out)
78  {}
79 
80  bool operator()(const MoochoPack::FilterEntry &entry)
81  {
82  if (
83  entry.f >= f_with_boundary_
84  &&
85  entry.theta >= theta_with_boundary_
86  )
87  {
88  if (!is_null(out_)) {
89  *out_
90  << "\nRemoving from the filter the redundant point:"
91  << "\n f_with_boundary = " << entry.f
92  << "\n theta_with_boundary = " << entry.theta
93  << "\n iteration added = " << entry.iter
94  << std::endl;
95  }
96  return true;
97  }
98  return false;
99  }
100 
101 private:
102 
103  const MoochoPack::value_type f_with_boundary_;
104  const MoochoPack::value_type theta_with_boundary_;
105  const Teuchos::RCP<std::ostream> out_;
106 
107 };
108 
109 
110 } // namespace
111 
112 
113 namespace MoochoPack {
114 
115 // This must exist somewhere already, ask Ross
117 { return (x < y) ? x : y; }
118 
120 { return (x > y) ? x : y; }
121 
124  ,const std::string obj_iq_name
125  ,const std::string grad_obj_iq_name
126  ,const value_type &gamma_theta
127  ,const value_type &gamma_f
128  ,const value_type &f_min
129  ,const value_type &gamma_alpha
130  ,const value_type &delta
131  ,const value_type &s_f
132  ,const value_type &s_theta
133  ,const value_type &theta_small_fact
134  ,const value_type &theta_max
135  ,const value_type &eta_f
136  ,const value_type &back_track_frac
137  )
138  :
139  gamma_theta_(gamma_theta),
140  gamma_f_(gamma_f),
141  f_min_(f_min),
142  gamma_alpha_(gamma_alpha),
143  delta_(delta),
144  s_f_(s_f),
145  s_theta_(s_theta),
146  theta_small_fact_(theta_small_fact),
147  theta_max_(theta_max),
148  eta_f_(eta_f),
149  back_track_frac_(back_track_frac),
150  filter_(FILTER_IQ_STRING),
151  obj_f_(obj_iq_name),
152  grad_obj_f_(grad_obj_iq_name),
153  nlp_(nlp)
154 {
156  !nlp_.get(),
157  std::logic_error,
158  "Null nlp passed to LineSearchFilter_Step constructor"
159  );
160 
161 #if defined(FILTER_DEBUG_OUT)
162  std::ofstream fout("filter_out.xml", std::ofstream::out | std::ofstream::trunc);
163  fout << "<FilterDebugDocument>" << std::endl;
164  fout.close();
165 #endif
166 }
167 
169 {
170 #if defined(FILTER_DEBUG_OUT)
171  std::ofstream fout("filter_out.xml", std::ofstream::out | std::ofstream::app);
172  fout << "</FilterDebugDocument>" << std::endl;
173  fout.close();
174 #endif
175 }
176 
178  Algorithm& _algo, poss_type step_poss,
180  ,poss_type assoc_step_poss)
181 {
182 
183  using Teuchos::dyn_cast;
185  using LinAlgOpPack::Vp_StV;
186  using std::setw;
187 
188  // Get Algorithm (cast), state, and problem
189  NLPAlgo &algo = rsqp_algo(_algo);
190  NLPAlgoState &s = algo.rsqp_state();
191 
192  EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level();
193  std::ostream &out = algo.track().journal_out();
194 
195  // print step header
196  if (static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS))
197  {
199  print_algorithm_step( algo, step_poss, type, assoc_step_poss, out );
200  }
201 
203  nlpOutputTempState(
204  nlp_, Teuchos::getFancyOStream(Teuchos::rcp(&out,false)),
206  // Above, we don't want to litter the output with any trace from the NLP.
207  // However, if the user forces the verbosity level to be increased, then we
208  // want to set the stream so that it knows where to print to.
209 
210  const size_type
211  m = nlp_->m();
212 
213  // Get the iteration quantity container objects
214  IterQuantityAccess<value_type>
215  &f_iq = obj_f_(s),
216  &alpha_iq = s.alpha();
217 
218  IterQuantityAccess<VectorMutable>
219  &x_iq = s.x(),
220  *c_iq = m > 0 ? &s.c() : NULL,
221  *h_iq = NULL, // RAB: Replace latter!
222  &Gf_iq = grad_obj_f_(s);
223 
224  // check that all the pertinent information is known
225  if (!s.d().updated_k(0) || !x_iq.updated_k(0))
226  {
227  // Dead in the water
228  TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Error, d_k or x_k not updated." );
229  return false;
230  }
231 
232  if (!alpha_iq.updated_k(0) || alpha_iq.get_k(0) > 1 || alpha_iq.get_k(0) <= 0)
233  {
234  // if alpha_k is not known then we would need to calculate all the new points
235  TEUCHOS_TEST_FOR_EXCEPTION( true, std::out_of_range, "Error, alpha_k not updated or out of range [0, 1)." );
236  return false;
237  }
238 
239  // Setup some necessary parameters
240  // Assuming that f_iq, Gf_iq, c_iq, h_iq are updated for k
241  const value_type Gf_t_dk =
242  (
243  Gf_iq.updated_k(0)
244  ? Gf_iq.get_k(0).inner_product( s.d().get_k(0) )
245  : dyn_cast<NLPInterfacePack::NLPObjGrad>(*nlp_).calc_Gf_prod(
246  x_iq.get_k(0),s.d().get_k(0)
247  )
248  );
249  const value_type theta_k = CalculateTheta_k( c_iq, h_iq, 0);
250  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
251  out << "\ntheta_k = ||c_k||1/c_k.dim() = " << theta_k << std::endl;
252  const value_type gamma_f_used = CalculateGammaFUsed(f_iq,theta_k,olevel,out);
253  const value_type theta_small = theta_small_fact_ * MAX(1.0,theta_k);
254  const value_type alpha_min = CalculateAlphaMin( gamma_f_used, Gf_t_dk, theta_k, theta_small );
255 
256  value_type &alpha_k = alpha_iq.get_k(0);
257  value_type theta_kp1 = 0.0;;
258 
259  // Print out some header/initial information
260  int w = 15;
261  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
262  {
263  out << "\nBeginning Filter line search method.\n"
264  << "\nCurrent Filter\n"
265  << "-----------------------------------------------------\n"
266  << "|" << setw(25) << "f_with_boundary "
267  << "|" << setw(25) << "theta_with_boundary "
268  << "|\n"
269  << "-----------------------------------------------------\n";
270 
271  IterQuantityAccess<Filter_T>& filter_iq = filter_(s);
272 
273  if (filter_iq.updated_k(-1)) {
274  Filter_T& filter = filter_iq.get_k(-1);
275  if (!filter.empty()) {
276  for (
277  Filter_T::iterator entry = filter.begin();
278  entry != filter.end();
279  ++entry
280  )
281  {
282  out << "|" << setw(25) << entry->f
283  << " " << setw(25) << entry->theta
284  << "|\n";
285  }
286  }
287  else {
288  out << "Filter is empty.\n";
289  }
290  }
291  else {
292  out << "Filter is empty.\n";
293  }
294 
295  // dump header
296  out << "\n Iteration Status\n";
297  out << "----------------------------------------------------------------------------------------------------------\n";
298 
299  out << "|" << setw(w) << "alpha_k "
300  << "|" << setw(w) << "f_kp1 "
301  << "|" << setw(w) << "theta_kp1 "
302  << "|" << setw(w) << "pt. status "
303  << "|" << setw(40) << "comment "
304  << "|" << std::endl;
305 
306  out << "----------------------------------------------------------------------------------------------------------"
307  << std::endl;
308  }
309 
310  // Begin the line search
311  bool augment_filter = false;
312  bool accepted = false;
313  while (alpha_k > alpha_min && !accepted)
314  {
315  accepted = true;
316 
317  // Check that point is safe for calculations (no nans, infs, etc)
318  if (!ValidatePoint(x_iq, f_iq, c_iq, h_iq, false))
319  {
320  accepted = false;
321 
322  // Print out some point information
323  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
324  {
325  int w = 15;
326  // dump point
327  out << "|" << setw(w) << " --- "
328  << " " << setw(w) << " --- "
329  << " " << setw(w) << " --- "
330  << " " << setw(w) << " failed "
331  << " " << setw(40) << " nan_or_inf in calc"
332  << " " << std::endl;
333  }
334 
335  // Really, we do not need to throw an exception here, we can try and backtrack
336  // alpha to get into an acceptable region
337  TEUCHOS_TEST_FOR_EXCEPTION( true, std::out_of_range, "Point Not Valid." );
338  }
339 
340  // Check if point satisfies filter
341  if (accepted)
342  {
343  theta_kp1 = CalculateTheta_k(c_iq, h_iq, +1);
344 
345  // Print out some point information
346  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
347  {
348  // dump point
349  out << "|" << setw(w) << alpha_k
350  << " " << setw(w) << f_iq.get_k(+1)
351  << " " << setw(w) << theta_kp1;
352  }
353 
354  accepted = CheckFilterAcceptability(f_iq.get_k(+1), theta_kp1, s);
355 
356  // Print out failure information
357  if( !accepted && static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
358  {
359  out << " " << setw(w) << "failed"
360  << " " << setw(40) << "Unacceptable to filter"
361  << "|" << std::endl;
362  }
363  }
364 
365  // Check if point has theta less than theta_max
366  if (accepted) {
367  if (theta_kp1 > theta_max_) {
368  accepted = false;
369  // Print out failure information
370  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
371  out << " " << setw(w) << "failed"
372  << " " << setw(40) << "theta_kp1 > theta_max"
373  << "|" << std::endl;
374  }
375  }
376  }
377 
378 
379  // Check if point satisfies sufficient decrease (Armijo on f if switching cond holds)
380  if (accepted)
381  {
382  // Check for switching condition
383  if (ShouldSwitchToArmijo(Gf_t_dk, alpha_k, theta_k, theta_small))
384  {
385  accepted = CheckArmijo(Gf_t_dk, alpha_k, f_iq);
386 
387  // Print out point information
388  if(static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
389  {
390  if (accepted)
391  { out << " " << setw(w) << "accepted"; }
392  else
393  { out << " " << setw(w) << "failed"; }
394 
395  out << " " << setw(40) << "Switch Cond. Holds (Armijo)" << "|" << std::endl;
396  }
397  }
398  else
399  {
400  accepted = CheckFractionalReduction(f_iq, gamma_f_used, theta_kp1, theta_k);
401  if (accepted)
402  { augment_filter = true; }
403 
404  // Print out point information
405  if(static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
406  {
407  if (accepted)
408  { out << " " << setw(w) << "accepted"; }
409  else
410  { out << " " << setw(w) << "failed"; }
411 
412  out << " " << setw(40) << "Fraction Reduction (! Switch Cond )" << "|" << std::endl;
413  }
414 
415  }
416  }
417 
418  // if the point fails any of the tests, then backtrack
419  if (!accepted)
420  {
421  // try a smaller alpha_k
422  alpha_k = alpha_k*back_track_frac_;
423  UpdatePoint(s.d().get_k(0), alpha_k, x_iq, f_iq, c_iq, h_iq, *nlp_);
424  }
425 
426  } // end while
427 
428 
429  if (accepted)
430  {
431  // Print status
432  if(static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
433  if (augment_filter)
434  out << "\nPoint was accepted - augmenting the filter ...\n";
435  else
436  out << "Point was accepted - did NOT augment filter.\n";
437  }
438 
439  if (augment_filter) {
440  AugmentFilter( gamma_f_used, f_iq.get_k(+1), theta_kp1, s, olevel, out );
441  }
442  else {
443  // Just update the filter from the last iteration
444  UpdateFilter(s);
445  }
446  }
447  else {
448  // Could not find an acceptable alpha_k, go to restoration
449  // Print status
450  //if(static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) )
451  // {
452  // out << "\nCould not find acceptable alpha_k - going to restoration phase.\n";
453  // }
454 
455  //TEUCHOS_TEST_FOR_EXCEPTION( true, std::out_of_range, "Tried to go to restoration phase." );
456 
458  ,"FilterLineSearchFailure : Should go to restoration"
459  );
460  }
461 
462  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_VECTORS) )
463  {
464  out << "\nx_kp1 =\n" << x_iq.get_k(+1);
465  if (c_iq)
466  { out << "\nc_kp1 =\n" << c_iq->get_k(+1); }
467  if (h_iq)
468  { out << "\nh_kp1 =\n" << h_iq->get_k(+1); }
469  }
470 
471 #if defined(FILTER_DEBUG_OUT)
472  std::ofstream fout("filter_out.xml", std::ofstream::out | std::ostream::app);
473  fout << " <FilterIteration iter=\"" << s.k() << "\">" << std::endl;
474  fout << " <SelectedPoint alpha=\"" << alpha_k
475  << "\" f=\"" << f_iq.get_k(+1)
476  << "\" theta=\"" << theta_kp1
477  << "\" />" << std::endl;
478 
479  // Output the filter
480  fout << " <Filter>" << std::endl;
481 
482  IterQuantityAccess<Filter_T>& filter_iq = filter_(s);
483  if (filter_iq.updated_k(0))
484  {
485  Filter_T& current_filter = filter_iq.get_k(0);
486  for (
487  Filter_T::iterator entry = current_filter.begin();
488  entry != current_filter.end();
489  ++entry
490  )
491  {
492  fout << " <FilterPoint iter=\"" << entry->iter
493  << "\" f=\"" << entry->f
494  << "\" theta=\"" << entry->theta << ">" << std::endl;
495  }
496  }
497  else
498  {
499  fout << " <FilterNotUpdated/>" << std::endl;
500  }
501 
502  fout << " </Filter>" << std::endl;
503 
504 
505  // Output the alpha curve
506  fout << " <AlphaCurve>" << std::endl;
507  value_type alpha_tmp = 1.0;
508  for (int i = 0; i < 10 || alpha_tmp > alpha_k; ++i)
509  {
510  UpdatePoint(s.d().get_k(0), alpha_tmp, x_iq, f_iq, c_iq, h_iq, *nlp_);
511  if (ValidatePoint(x_iq, f_iq, c_iq, h_iq, false))
512  {
513  value_type theta = CalculateTheta_k(c_iq, h_iq, +1);
514  fout << " <AlphaPoint "
515  << "alpha=\"" << alpha_tmp << "\" "
516  << "f=\"" << f_iq.get_k(+1) << "\" "
517  << "theta=\"" << theta << ">" << std::endl;
518  }
519 
520  alpha_tmp=alpha_tmp*back_track_frac_;
521  }
522 
523  // restore alpha_k
524  UpdatePoint(s.d().get_k(0), alpha_k, x_iq, f_iq, c_iq, h_iq, *nlp_);
525 
526  fout << " </AlphaCurve>" << std::endl;
527 
528  fout << " </FilterIteration" << std::endl;
529 
530  fout.close();
531 
532 #endif
533 
534  return true;
535 }
536 
538  const Algorithm& _algo, poss_type step_poss, IterationPack::EDoStepType type
539  ,poss_type assoc_step_poss, std::ostream& out, const std::string& L
540  ) const
541 {
542  out
543  << L << "*** Filter line search method\n"
544  << L << "# Assumes initial d_k & alpha_k (0-1) is known and\n"
545  << L << "# x_kp1, f_kp1, c_kp1 and h_kp1 are calculated for that alpha_k\n"
546  << L << "Gf_t_dk = <Gf,dk>\n"
547  << L << "theta_k = norm_1(c_k)/c_k.dim()\n"
548  << L << "theta_small = theta_small_fact*max(1.0,theta_k)\n"
549  << L << "if f_min != F_MIN_UNBOUNDED then\n"
550  << L << " gamma_f_used = gamma_f * (f_k-f_min)/theta_k\n"
551  << L << "else\n"
552  << L
553  << L << " gamma_f_used = gamma_f\n"
554  << L << "end\n"
555  << L << "if Gf_t_dk < 0 then\n"
556  << L << " alpha_min = min(gamma_theta, gamma_f_used*theta_k/(-Gf_t_dk))\n"
557  << L << " if theta_k <= theta_small then\n"
558  << L << " alpha_min = min(alpha_min, delta_*(theta_k^s_theta)/((-Gf_t_dk)^s_f))\n"
559  << L << " end\n"
560  << L << "else\n"
561  << L << " alpha_min = gamma_theta\n"
562  << L << "end\n"
563  << L << "alpha_min = alpha_min*gamma_alpha\n"
564  << L << "# Start the line search\n"
565  << L << "accepted = false\n"
566  << L << "augment = false\n"
567  << L << "while alpha > alpha_min and accepted = false then\n"
568  << L << " accepted = true"
569  << L << " if any values in x_kp1, f_kp1, c_kp1, h_kp1 are nan or inf then\n"
570  << L << " accepted = false\n"
571  << L << " end\n"
572  << L << " # Check filter\n"
573  << L << " if accepted = true then\n"
574  << L << " theta_kp1 = norm_1(c_kp1)/c_kp1.dim()\n"
575  << L << " for each pt in the filter do\n"
576  << L << " if theta_kp1 >= pt.theta and f_kp1 >= pt.f then\n"
577  << L << " accepted = false\n"
578  << L << " break for\n"
579  << L << " end\n"
580  << L << " next pt\n"
581  << L << " end\n"
582  << L << " #Check Sufficient Decrease\n"
583  << L << " if accepted = true then"
584  << L << " # if switching condition is satisfied, use Armijo on f\n"
585  << L << " if theta_k < theta_small and Gf_t_dk < 0 and\n"
586  << L << " ((-Gf_t_dk)^s_f)*alpha_k < delta*theta_k^s_theta then\n"
587  << L << " if f_kp1 <= f_k + eta_f*alpha_k*Gf_t_dk then\n"
588  << L << " accepted = true\n"
589  << L << " end\n"
590  << L << " else\n"
591  << L << " # Verify factional reduction\n"
592  << L << " if theta_kp1 < (1-gamma_theta)*theta_k or f_kp1 < f_k - gamma_f_used*theta_k then\n"
593  << L << " accepted = true\n"
594  << L << " augment = true\n"
595  << L << " end\n"
596  << L << " end\n"
597  << L << " end\n"
598  << L << " if accepted = false then\n"
599  << L << " alpha_k = alpha_k*back_track_frac\n"
600  << L << " x_kp1 = x_k + alpha_k * d_k\n"
601  << L << " f_kp1 = f(x_kp1)\n"
602  << L << " c_kp1 = c(x_kp1)\n"
603  << L << " h_kp1 = h(x_kp1)\n"
604  << L << " end\n"
605  << L << "end while\n"
606  << L << "if accepted = true then\n"
607  << L << " if augment = true then\n"
608  << L << " Augment the filter (use f_with_boundary and theta_with_boundary)\n"
609  << L << " end\n"
610  << L << "else\n"
611  << L << " goto the restoration phase\n"
612  << L << "end\n";
613 }
614 
616  const IterQuantityAccess<VectorMutable>& x,
617  const IterQuantityAccess<value_type>& f,
618  const IterQuantityAccess<VectorMutable>* c,
619  const IterQuantityAccess<VectorMutable>* h,
620  const bool throw_excpt
621  ) const
622 {
623 
625 
626  if (assert_print_nan_inf(x.get_k(+1), "x", throw_excpt, NULL)
627  || assert_print_nan_inf(f.get_k(+1), "f", throw_excpt, NULL)
628  || (!c || assert_print_nan_inf(c->get_k(+1), "c", throw_excpt, NULL))
629  || (!h || assert_print_nan_inf(h->get_k(+1), "c", throw_excpt, NULL)))
630  {
631  return true;
632  }
633  return false;
634 }
635 
637  const value_type f,
638  const value_type theta,
639  const AlgorithmState& s
640  ) const
641 {
642  bool accepted = true;
643 
644  const IterQuantityAccess<Filter_T>& filter_iq = filter_(s);
645 
646  if (filter_iq.updated_k(-1))
647  {
648  const Filter_T &current_filter = filter_iq.get_k(-1);
649 
650  for (
651  Filter_T::const_iterator entry = current_filter.begin();
652  entry != current_filter.end();
653  ++entry
654  )
655  {
656  if (f >= entry->f && theta >= entry->theta)
657  {
658  accepted = false;
659  break;
660  }
661  }
662  }
663 
664  return accepted;
665 }
666 
668  const value_type Gf_t_dk,
669  const value_type alpha_k,
670  const IterQuantityAccess<value_type>& f_iq
671  ) const
672 {
673  bool accepted = false;
674 
675  // Check Armijo on objective fn
676  double f_kp1 = f_iq.get_k(+1);
677  double f_k = f_iq.get_k(0);
678  double lhs = f_k - f_kp1;
679  double rhs = -eta_f_*alpha_k*Gf_t_dk;
680  if ( lhs >= rhs )
681  {
682  // Accept pt, do NOT augment filter
683  accepted = true;
684  }
685 
686  return accepted;
687 }
688 
690  const IterQuantityAccess<value_type>& f_iq,
691  const value_type gamma_f_used,
692  const value_type theta_kp1,
693  const value_type theta_k
694  ) const
695 {
696  bool accepted = false;
697  if (theta_kp1 <= (1-gamma_theta_)*theta_k
698  || f_iq.get_k(+1) <= f_iq.get_k(0)-gamma_f_used*theta_k )
699  {
700  // Accept pt and augment filter
701  accepted = true;
702  }
703  return accepted;
704 }
705 
707  const VectorMutable& d,
708  const value_type alpha,
709  IterQuantityAccess<VectorMutable> &x,
710  IterQuantityAccess<value_type>& f,
711  IterQuantityAccess<VectorMutable>* c,
712  IterQuantityAccess<VectorMutable>* h,
713  NLP& nlp ) const
714 {
715  using LinAlgOpPack::Vp_StV;
717  VectorMutable& x_kp1 = x.set_k(+1);
718  x_kp1 = x.get_k(0);
719  Vp_StV( &x_kp1, alpha, d);
720 
721  if (assert_print_nan_inf(x_kp1, "x", true, NULL))
722  {
723  // Calcuate f and c at the new point.
724  nlp.unset_quantities();
725  nlp.set_f( &f.set_k(+1) );
726  if (c) nlp.set_c( &c->set_k(+1) );
727  nlp.calc_f( x_kp1 );
728  if (c) nlp.calc_c( x_kp1, false );
729  nlp.unset_quantities();
730  }
731 }
732 
734  const value_type gamma_f_used,
735  const value_type Gf_t_dk,
736  const value_type theta_k,
737  const value_type theta_small
738  ) const
739 {
740  value_type alpha_min = 0;
741 
742  if (Gf_t_dk < 0)
743  {
744  alpha_min = MIN(gamma_theta_, gamma_f_used*theta_k/(-Gf_t_dk));
745  if (theta_k <= theta_small)
746  {
747  value_type switch_bound = delta_*pow(theta_k, s_theta_)/pow(-Gf_t_dk,s_f_);
748  alpha_min = MIN(alpha_min, switch_bound);
749  }
750  }
751  else
752  {
753  alpha_min = gamma_theta_;
754  }
755  return alpha_min * gamma_alpha_;
756 }
757 
759  const IterQuantityAccess<VectorMutable>* c,
760  const IterQuantityAccess<VectorMutable>* h,
761  int k
762  ) const
763 {
764  value_type theta = 0.0;
765  if (h) {
766  TEUCHOS_TEST_FOR_EXCEPTION( true, std::out_of_range, "Error, do not support inequalities yet" );
767  }
768  if (c) {
769  const Vector &c_k = c->get_k(k);
770  theta += ( c_k.norm_1() / c_k.dim() );
771  }
772  return theta;
773 }
774 
776  const IterQuantityAccess<value_type> &f,
777  const value_type theta_k,
778  const EJournalOutputLevel olevel,
779  std::ostream &out
780  ) const
781 {
782  if( f_min() == F_MIN_UNBOUNDED) {
783  if((int)olevel >= static_cast<int>(PRINT_ALGORITHM_STEPS))
784  out << "\nf_min==F_MIN_UNBOUNDED: Setting gamma_f_used = gamma_f = "<<gamma_f()<<".\n";
785  return gamma_f();
786  }
787  const value_type f_k = f.get_k(0);
788  if( f_k < f_min() ) {
789  if((int)olevel >= static_cast<int>(PRINT_ALGORITHM_STEPS))
790  out << "\nWarning!!! f_k = "<<f_k<<" < f_min = "<<f_min()<<"! Setting gamma_f_used = gamma_f = "<<gamma_f()<<".\n";
791  return gamma_f();
792  }
793  const value_type gamma_f_used = gamma_f() * ( f_k - f_min() ) / theta_k;
794  if((int)olevel >= static_cast<int>(PRINT_ALGORITHM_STEPS))
795  out << "\nf_min = "<<f_min()<<"!=F_MIN_UNBOUNDED: Setting gamma_f_used = gamma_f * (f_k - f_min)/theta_k = "
796  <<gamma_f()<<" * ("<<f_k<<" - "<<f_min()<<")/"<<theta_k<<" = "<<gamma_f_used <<".\n";
797  return gamma_f_used;
798 }
799 
801  const value_type Gf_t_dk,
802  const value_type alpha_k,
803  const value_type theta_k,
804  const value_type theta_small
805  ) const
806 {
807  if (theta_k < theta_small && Gf_t_dk < 0) {
808  if (pow(-Gf_t_dk, s_f_)*alpha_k - delta_*pow(theta_k, s_theta_) > 0) {
809  return true;
810  }
811  }
812  return false;
813 }
814 
815 
817 {
818 
819  IterQuantityAccess<Filter_T>& filter_iq = filter_(s);
820 
821  if (!filter_iq.updated_k(0))
822  {
823  if (filter_iq.updated_k(-1))
824  {
825  // initialize the filter from the last iteration
826  filter_iq.set_k(0,-1);
827  }
828  else
829  {
830  // create an uninitialized filter
831  filter_iq.set_k(0);
832  }
833  }
834 
835 }
836 
838  const value_type gamma_f_used,
839  const value_type f,
840  const value_type theta,
842  const EJournalOutputLevel olevel,
843  std::ostream &out
844  ) const
845 {
846 
847  using Teuchos::as;
848 
849  const value_type
850  f_with_boundary = f-gamma_f_used*theta,
851  theta_with_boundary = (1.0-gamma_theta())*theta;
852 
853  if(static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
854  out << "\nAugmenting the filter with the point:"
855  << "\n f_with_boundary = f_kp1 - gamma_f_used*theta_kp1 = "<<f<<" - "<<gamma_f_used<<"*"<<theta<< " = " <<f_with_boundary
856  << "\n theta_with_boundary = (1-gamma_theta)*theta_kp1 = (1-"<<gamma_theta()<<")*"<<theta<<" = "<<theta_with_boundary
857  << std::endl;
858  }
859 
860  UpdateFilter(s);
861  Filter_T& current_filter = filter_(s).get_k(0);
862 
863  // Remove current filter entries that are not longer needed
864  current_filter.remove_if(
865  RemoveFilterEntryPred(
866  f_with_boundary, theta_with_boundary,
867  as<int>(olevel) >= as<int>(PRINT_ALGORITHM_STEPS)
868  ? Teuchos::rcpFromRef(out) : Teuchos::null
869  )
870  );
871 
872  // Now append the current point
873  current_filter.push_front(FilterEntry(f_with_boundary, theta_with_boundary, s.k()));
874 
875 }
876 
877 // static
878 
880 
881 } // end namespace MoochoPack
void UpdateFilter(IterationPack::AlgorithmState &s) const
AbstractLinAlgPack::size_type size_type
bool is_null(const boost::shared_ptr< T > &p)
const std::string FILTER_IQ_STRING
bool CheckFractionalReduction(const IterQuantityAccess< value_type > &f_iq, const value_type gamma_f_used, const value_type theta_kp1, const value_type theta_k) const
void pow(DVectorSlice *vs_lhs, const DVectorSlice &vs_rhs1, const DVectorSlice &vs_rhs2)
vs_lhs = pow(vs_rhs1,vs_rhs2)
value_type CalculateAlphaMin(const value_type gamma_f_used, const value_type Gf_t_dk, const value_type theta_k, const value_type theta_small) const
bool CheckArmijo(const value_type Gf_t_dk, const value_type alpha_k, const IterQuantityAccess< value_type > &f_iq) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void Vp_StV(VectorMutable *v_lhs, const value_type &alpha, const Vector &v_rhs)
v_lhs = alpha * v_rhs + v_lhs
rSQP Algorithm control class.
value_type CalculateGammaFUsed(const IterQuantityAccess< value_type > &f, const value_type theta_k, const EJournalOutputLevel olevel, std::ostream &out) const
T * get() const
LineSearchFilter_Step(Teuchos::RCP< NLPInterfacePack::NLP > nlp, const std::string obj_iq_name="f", const std::string grad_obj_iq_name="Gf", const value_type &gamma_theta=1e-5, const value_type &gamma_f=1e-5, const value_type &f_min=F_MIN_UNBOUNDED, const value_type &gamma_alpha=5e-2, const value_type &delta=1e-4, const value_type &s_theta=1.1, const value_type &s_f=2.3, const value_type &theta_small_fact=1e-4, const value_type &theta_max=1e10, const value_type &eta_f=1e-4, const value_type &back_track_frac=0.5)
Constructor.
value_type MIN(value_type x, value_type y)
bool ValidatePoint(const IterQuantityAccess< VectorMutable > &x, const IterQuantityAccess< value_type > &f, const IterQuantityAccess< VectorMutable > *c, const IterQuantityAccess< VectorMutable > *h, const bool throw_excpt) const
CastIQMember< VectorMutable > grad_obj_f_
ITeration quantity access for objective gradient.
bool do_step(Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss)
std::list< FilterEntry > Filter_T
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const f_int f_dbl_prec const f_int f_int const f_int f_int const f_dbl_prec f_int f_int f_dbl_prec w[]
virtual std::ostream & journal_out() const
Return a reference to a std::ostream to be used to output debug information and the like...
value_type CalculateTheta_k(const IterQuantityAccess< VectorMutable > *c, const IterQuantityAccess< VectorMutable > *h, int k) const
Thrown if a line search failure occurs.
EJournalOutputLevel
enum for journal output.
T_To & dyn_cast(T_From &from)
Reduced space SQP state encapsulation interface.
std::ostream * out
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
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.
Teuchos::RCP< NLPInterfacePack::NLP > nlp_
Abstacts a set of iteration quantities for an iterative algorithm.
void AugmentFilter(const value_type gamma_f_used, const value_type f_with_boundary, const value_type theta_with_boundary, IterationPack::AlgorithmState &s, const EJournalOutputLevel olevel, std::ostream &out) const
AlgorithmTracker & track()
TypeTo as(const TypeFrom &t)
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...
CastIQMember< value_type > obj_f_
Iteration quantity access for objective value.
const f_dbl_prec const f_int const f_int const f_int f_dbl_prec rhs[]
bool ShouldSwitchToArmijo(const value_type Gf_t_dk, const value_type alpha_k, const value_type theta_k, const value_type theta_small) const
bool CheckFilterAcceptability(const value_type f, const value_type theta, const AlgorithmState &s) const
AbstractLinAlgPack::value_type value_type
Acts as the central hub for an iterative algorithm.
NLPAlgoState & rsqp_state()
<<std aggr>="">> members for algo_cntr
void UpdatePoint(const VectorMutable &d, value_type alpha, IterQuantityAccess< VectorMutable > &x, IterQuantityAccess< value_type > &f, IterQuantityAccess< VectorMutable > *c, IterQuantityAccess< VectorMutable > *h, NLP &nlp) const
virtual size_type m() const
Return the number of general equality constraints.
NLPAlgo & rsqp_algo(Algorithm &algo)
Convert from a Algorithm to a NLPAlgo.
value_type MAX(value_type x, value_type y)