1 //------------------------------------------------------------------------
2 // Copyright (C) 1993:
3 // J.C. Meza
4 // Sandia National Laboratories
5 // meza@california.sandia.gov
6 //------------------------------------------------------------------------
7
8 #include "Opt.h"
9 #include "ioformat.h"
10
11 using NEWMAT::ColumnVector;
12 using NEWMAT::SymmetricMatrix;
13
14 namespace OPTPP {
15
trustregion(NLP1 * nlp,ostream * fout,SymmetricMatrix & H,ColumnVector & search_dir,ColumnVector & sx,real & TR_size,real & step_length,real stpmax,real stpmin)16 int trustregion(NLP1* nlp, ostream *fout,
17 SymmetricMatrix& H, ColumnVector& search_dir,
18 ColumnVector& sx, real& TR_size, real& step_length,
19 real stpmax, real stpmin)
20 {
21 /****************************************************************************
22 * subroutine trustregion
23 *
24 * Purpose
25 * find a step which satisfies the Goldstein-Armijo line search conditions
26 *
27 * Compute the dogleg step
28 * Compute the predicted reduction, pred, of the quadratic model
29 * Compute the actual reduction, ared
30 * IF ared/pred > eta
31 * THEN x_vec = x_vec + d_vec
32 * TR_size >= TR_size
33 * Compute the gradient g_vec at the new point
34 * ELSE TR_size < ||d_vec||
35 *
36 * Parameters
37 * nlp --> pointer to nonlinear problem object
38 *
39 * search_dir --> Vector of length n which specifies the
40 * newton direction on input. On output it will
41 * contain the step
42 *
43 * step_length <-- is a nonnegative variable.
44 * On output step_length contains the step size taken
45 *
46 * ftol --> default Value = 1.e-4
47 * ftol should be smaller than 5.e-1
48 * suggested value = 1.e-4 for newton methods
49 * = 1.e-1 for more exact line searches
50 * xtol --> default Value = 2.2e-16
51 * gtol --> default Value = 0.9
52 * gtol should be greater than 1.e-4
53 *
54 * termination occurs when the sufficient decrease
55 * condition and the directional derivative condition are
56 * satisfied.
57 *
58 * stpmin and TR_size are nonnegative input variables which
59 * specify lower and upper bounds for the step.
60 * stpmin Default Value = 1.e-9
61 *
62 * Initial version Juan Meza November 1994
63 *
64 *
65 *****************************************************************************/
66
67 // Local variables
68
69 int n = nlp->getDim();
70 bool debug = nlp->getDebug();
71 bool modeOverride = nlp->getModeOverride();
72
73 ColumnVector tgrad(n), newton_dir(n), tvec(n), xc(n), xtrial(n);
74 real fvalue, fplus, dnorm;
75 real eta1 = .001;
76 real eta2 = .1;
77 real eta3 = .75;
78 real rho_k;
79 int iter = 0;
80 int iter_max = 100;
81 real dd1, dd2;
82 real ared, pred;
83 int dog_step;
84 real TR_MAX = stpmax;
85 static char *steps[] = {"C", "D", "N", "B"};
86 static bool accept;
87
88 //
89 // Initialize variables
90 //
91
92 fvalue = nlp->getF();
93 xc = nlp->getXc();
94 step_length = 1.0;
95 tgrad = nlp->getGrad();
96 newton_dir = search_dir;
97
98 if (debug) {
99 *fout << "\n***************************************";
100 *fout << "***************************************\n";
101 *fout << "\nComputeStep using trustregion\n";
102 *fout << "\tStep ||step|| ared pred TR_size \n";
103 }
104
105 while (iter < iter_max) {
106 iter++;
107 //
108 // Compute the dogleg step
109 //
110 search_dir = newton_dir;
111 dog_step = dogleg(nlp, fout, H, tgrad, search_dir, sx, dnorm, TR_size, stpmax);
112 step_length = dnorm;
113 //
114 // Compute pred = -g'd - 1/2 d'Hd
115 //
116 dd1 = Dot(tgrad,search_dir);
117 tvec = H * search_dir;
118 dd2 = Dot(search_dir,tvec);
119 pred = -dd1 - dd2/2.0;
120
121 //
122 // Compute objective function at trial point
123 //
124
125 xtrial = xc + search_dir;
126 if (modeOverride) {
127 nlp->setX(xtrial);
128 nlp->eval();
129 fplus = nlp->getF();
130 }
131 else
132 fplus = nlp->evalF(xtrial);
133 ared = fvalue - fplus;
134
135 //
136 // Should we take this step ?
137 //
138
139 rho_k = ared/pred;
140
141 accept = false;
142 if (rho_k >= eta1) accept = true;
143
144 //
145 // Update the trust region
146 //
147
148 if (accept) {
149
150 //
151 // Do the standard updating
152 //
153
154 if (rho_k <= eta2) {
155
156 // Model is just sort of bad
157 // New trust region will be TR_size/2
158
159 if (debug) {
160 *fout << "trustregion: rho_k = " << e(rho_k,14,4)
161 << " eta2 = " << e(eta2,14,4) << "\n";
162 }
163 TR_size = step_length / 2.0;
164
165 if (TR_size < stpmin) {
166 *fout << "***** Trust region too small to continue.\n";
167 nlp->setX(xc);
168 nlp->setF(fvalue);
169 nlp->setGrad(tgrad);
170 return(-1);
171 }
172 }
173
174 else if ((eta3 <= rho_k) && (rho_k <= (2.0 - eta3))) {
175
176 // Model is PRETTY good
177 // Double trust region
178
179 if (debug) {
180 *fout << "trustregion: rho_k = " << e(rho_k,14,4)
181 << " eta3 = " << e(eta3,14,4) << "\n";
182 }
183 TR_size = min(2.0*TR_size, TR_MAX);
184 }
185
186 else {
187
188 //
189 // All other cases
190 //
191
192 TR_size = max(2.0*step_length,TR_size);
193 TR_size = min(TR_size, TR_MAX);
194 if (debug) {
195 *fout << "trustregion: rho_k = " << e(rho_k,14,4) << "\n";
196 }
197 }
198 }
199
200 else {
201
202 // Model is REALLY bad
203 //
204
205 TR_size = step_length/10.0;
206
207 if (debug) {
208 *fout << "trustregion: rho_k = " << e(rho_k,14,4) << "n"
209 << " eta1 = " << e(eta1,14,4) << "\n";
210 }
211 if (TR_size < stpmin) {
212 *fout << "***** Trust region too small to continue.\n";
213 nlp->setX(xc);
214 nlp->setF(fvalue);
215 nlp->setGrad(tgrad);
216 return(-1);
217 }
218 }
219
220 //
221 // Accept/Reject Step
222 //
223
224 if (accept) {
225 //
226 // Update x, f, and grad
227 //
228
229 if (!modeOverride) {
230 nlp->setX(xtrial);
231 nlp->setF(fplus);
232 nlp->evalG();
233 }
234
235 if (debug) {
236 *fout << "\t Step ||step|| ared pred TR_size \n";
237 *fout << "Accept " << steps[dog_step] << e(step_length,14,4)
238 << e(ared,14,4) << e(pred,14,4) << e(TR_size,14,4) << "\n";
239 }
240 return(dog_step);
241 }
242
243 else {
244 //
245 // Reject step
246 //
247
248 if (debug) {
249 *fout << "\t Step ||step|| ared pred TR_size \n";
250 *fout << "Reject " << steps[dog_step] << e(step_length,14,4)
251 << e(ared,14,4) << e(pred,14,4) << e(TR_size,14,4) << "\n";
252 }
253 }
254 }
255 nlp->setX(xc);
256 nlp->setF(fvalue);
257 nlp->setGrad(tgrad);
258 return(-1); // Too many iterations
259 }
260
261 } // namespace OPTPP
262