ROL
ROL_Brents.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Rapid Optimization Library (ROL) Package
4//
5// Copyright 2014 NTESS and the ROL contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef ROL_BRENTS_H
11#define ROL_BRENTS_H
12
17#include "ROL_LineSearch.hpp"
18#include "ROL_BackTracking.hpp"
19
20namespace ROL {
21
22template<class Real>
23class Brents : public LineSearch<Real> {
24private:
25 Real tol_;
26 int niter_;
27 bool test_;
28
29 ROL::Ptr<Vector<Real> > xnew_;
30// ROL::Ptr<LineSearch<Real> > btls_;
31
32public:
33
34 virtual ~Brents() {}
35
36 // Constructor
37 Brents( ROL::ParameterList &parlist ) : LineSearch<Real>(parlist) {
38 Real oem10(1.e-10);
39 ROL::ParameterList &list = parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").sublist("Brent's");
40 tol_ = list.get("Tolerance",oem10);
41 niter_ = list.get("Iteration Limit",1000);
42 test_ = list.get("Run Test Upon Initialization",true);
43// tol_ = parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").get("Bracketing Tolerance",1.e-8);
44// btls_ = ROL::makePtr<BackTracking<Real>>(parlist);
45 }
46
47 void initialize( const Vector<Real> &x, const Vector<Real> &s, const Vector<Real> &g,
49 LineSearch<Real>::initialize(x,s,g,obj,con);
50 xnew_ = x.clone();
51// btls_->initialize(x,s,g,obj,con);
52
53 if ( test_ ) {
54 if ( test_brents() ) {
55 std::cout << "Brent's Test Passed!\n";
56 }
57 else {
58 std::cout << "Brent's Test Failed!\n";
59 }
60 }
61 }
62
63 // Find the minimum of phi(alpha) = f(x + alpha*s) using Brent's method
64 void run( Real &alpha, Real &fval, int &ls_neval, int &ls_ngrad,
65 const Real &gs, const Vector<Real> &s, const Vector<Real> &x,
67 ls_neval = 0; ls_ngrad = 0;
68
69 // Get initial line search parameter
70 alpha = LineSearch<Real>::getInitialAlpha(ls_neval,ls_ngrad,fval,gs,x,s,obj,con);
71
72 // TODO: Bracketing
73
74 // Run Brents
75 ROL::Ptr<typename LineSearch<Real>::ScalarFunction> phi
76 = ROL::makePtr<typename LineSearch<Real>::Phi>(*xnew_,x,s,obj,con);
77 int neval = 0;
78 Real A(0), B = alpha;
79 run_brents(neval, fval, alpha, *phi, A, B);
80 ls_neval += neval;
81 }
82
83private:
84 void run_brents(int &neval, Real &fval, Real &alpha,
86 const Real A, const Real B) const {
87 neval = 0;
88 // ---> Set algorithmic constants
89 const Real zero(0), half(0.5), one(1), two(2), three(3), five(5);
90 const Real c = half*(three - std::sqrt(five));
91 const Real eps = std::sqrt(ROL_EPSILON<Real>());
92 // ---> Set end points and initial guess
93 Real a = A, b = B;
94 alpha = a + c*(b-a);
95 // ---> Evaluate function
96 Real fx = phi.value(alpha);
97 neval++;
98 // ---> Initialize algorithm storage
99 Real v = alpha, w = v, u(0), fu(0);
100 Real p(0), q(0), r(0), d(0), e(0);
101 Real fv = fx, fw = fx, tol(0), t2(0), m(0);
102 for (int i = 0; i < niter_; i++) {
103 m = half*(a+b);
104 tol = eps*std::abs(alpha) + tol_; t2 = two*tol;
105 // Check stopping criterion
106 if (std::abs(alpha-m) <= t2 - half*(b-a)) {
107 break;
108 }
109 p = zero; q = zero; r = zero;
110 if ( std::abs(e) > tol ) {
111 // Fit parabola
112 r = (alpha-w)*(fx-fv); q = (alpha-v)*(fx-fw);
113 p = (alpha-v)*q - (alpha-w)*r; q = two*(q-r);
114 if ( q > zero ) {
115 p *= -one;
116 }
117 q = std::abs(q);
118 r = e; e = d;
119 }
120 if ( std::abs(p) < std::abs(half*q*r) && p > q*(a-alpha) && p < q*(b-alpha) ) {
121 // A parabolic interpolation step
122 d = p/q; u = alpha + d;
123 // f must not be evaluated too close to a or b
124 if ( (u - a) < t2 || (b - u) < t2 ) {
125 d = (alpha < m) ? tol : -tol;
126 }
127 }
128 else {
129 // A golden section step
130 e = ((alpha < m) ? b : a) - alpha; d = c*e;
131 }
132 // f must not be evaluated too close to alpha
133 u = alpha + ((std::abs(d) >= tol) ? d : ((d > zero) ? tol : -tol));
134 fu = phi.value(u);
135 neval++;
136 // Update a, b, v, w, and alpha
137 if ( fu <= fx ) {
138 if ( u < alpha ) {
139 b = alpha;
140 }
141 else {
142 a = alpha;
143 }
144 v = w; fv = fw; w = alpha; fw = fx; alpha = u; fx = fu;
145 }
146 else {
147 if ( u < alpha ) {
148 a = u;
149 }
150 else {
151 b = u;
152 }
153 if ( fu <= fw || w == alpha ) {
154 v = w; fv = fw; w = u; fw = fu;
155 }
156 else if ( fu <= fv || v == alpha || v == w ) {
157 v = u; fv = fu;
158 }
159 }
160 }
161 fval = fx;
162 }
163
164 class testFunction : public LineSearch<Real>::ScalarFunction {
165 public:
166 Real value(const Real x) {
167 Real val(0), I(0), two(2), five(5);
168 for (int i = 0; i < 20; i++) {
169 I = (Real)(i+1);
170 val += std::pow((two*I - five)/(x-(I*I)),two);
171 }
172 return val;
173 }
174 };
175
176 bool test_brents(void) const {
177 ROL::Ptr<typename LineSearch<Real>::ScalarFunction> phi
178 = ROL::makePtr<testFunction>();
179 Real A(0), B(0), alpha(0), fval(0);
180 Real error(0), error_i(0);
181 Real zero(0), two(2), three(3);
182 int neval = 0;
183 std::vector<Real> fvector(19,zero), avector(19,zero);
184 fvector[0] = 3.6766990169; avector[0] = 3.0229153;
185 fvector[1] = 1.1118500100; avector[1] = 6.6837536;
186 fvector[2] = 1.2182217637; avector[2] = 11.2387017;
187 fvector[3] = 2.1621103109; avector[3] = 19.6760001;
188 fvector[4] = 3.0322905193; avector[4] = 29.8282273;
189 fvector[5] = 3.7583856477; avector[5] = 41.9061162;
190 fvector[6] = 4.3554103836; avector[6] = 55.9535958;
191 fvector[7] = 4.8482959563; avector[7] = 71.9856656;
192 fvector[8] = 5.2587585400; avector[8] = 90.0088685;
193 fvector[9] = 5.6036524295; avector[9] = 110.0265327;
194 fvector[10] = 5.8956037976; avector[10] = 132.0405517;
195 fvector[11] = 6.1438861542; avector[11] = 156.0521144;
196 fvector[12] = 6.3550764593; avector[12] = 182.0620604;
197 fvector[13] = 6.5333662003; avector[13] = 210.0711010;
198 fvector[14] = 6.6803639849; avector[14] = 240.0800483;
199 fvector[15] = 6.7938538365; avector[15] = 272.0902669;
200 fvector[16] = 6.8634981053; avector[16] = 306.1051233;
201 fvector[17] = 6.8539024631; avector[17] = 342.1369454;
202 fvector[18] = 6.6008470481; avector[18] = 380.2687097;
203 for ( int i = 0; i < 19; i++ ) {
204 A = std::pow((Real)(i+1),two);
205 B = std::pow((Real)(i+2),two);
206 run_brents(neval, fval, alpha, *phi, A, B);
207 error_i = std::max(std::abs(fvector[i]-fval)/fvector[i],
208 std::abs(avector[i]-alpha)/avector[i]);
209 error = std::max(error,error_i);
210 }
211 return (error < three*(std::sqrt(ROL_EPSILON<Real>())*avector[18]+tol_)) ? true : false;
212 }
213
214};
215
216}
217
218#endif
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Provides the interface to apply upper and lower bound constraints.
Real value(const Real x)
Implements a Brent's method line search.
void run_brents(int &neval, Real &fval, Real &alpha, typename LineSearch< Real >::ScalarFunction &phi, const Real A, const Real B) const
Brents(ROL::ParameterList &parlist)
void run(Real &alpha, Real &fval, int &ls_neval, int &ls_ngrad, const Real &gs, const Vector< Real > &s, const Vector< Real > &x, Objective< Real > &obj, BoundConstraint< Real > &con)
ROL::Ptr< Vector< Real > > xnew_
bool test_brents(void) const
virtual ~Brents()
void initialize(const Vector< Real > &x, const Vector< Real > &s, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &con)
Provides interface for and implements line searches.
virtual void initialize(const Vector< Real > &x, const Vector< Real > &s, const Vector< Real > &g, Objective< Real > &obj, BoundConstraint< Real > &con)
virtual Real getInitialAlpha(int &ls_neval, int &ls_ngrad, const Real fval, const Real gs, const Vector< Real > &x, const Vector< Real > &s, Objective< Real > &obj, BoundConstraint< Real > &con)
Provides the interface to evaluate objective functions.
Defines the linear algebra or vector space interface.
virtual ROL::Ptr< Vector > clone() const =0
Clone to make a new (uninitialized) vector.