OpenLB 1.7
Loading...
Searching...
No Matches
optimizerLBFGS.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012-2016 Mathias J. Krause, Benjamin Förster
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
29#ifndef OPTIMIZER_LBFGS_H
30#define OPTIMIZER_LBFGS_H
31
32#include "optimizerLineSearch.h"
33#include "utilities/norm.h"
34
35
36// All OpenLB code is contained in this namespace.
37namespace olb {
38
40namespace opti {
41
42
44
53template<typename S, typename C>
55
56private:
57 S _startLambda;
58
59 int _l;
60
61 S _startCoefH;
62
63 S** _sStore;
64 S** _yStore;
65 S* _rhoStore;
66 S* _alpha;
67
68 int _firstStore;
69 int _lastStore;
70
71 C _lastControl;
72 C _lastDerivative;
73
74 mutable OstreamManager clout;
75
76public:
78 int dimCtrl, S eps, int maxIt, S lambda, int maxStepAttempts,
79 std::string stepCondition, int l, S startCoefH, bool verboseOn=true,
80 const std::string fname="", const std::string logFileName="",
81 bool withUpperBound=false, S upperBound=S(),
82 bool withLowerBound=false, S lowerBound=S(), bool vectorBounds=false,
83 S controlEps=S(std::numeric_limits<double>::epsilon() ), bool failOnMaxIter = true,
84 std::vector<OptimizerLogType> gplotAnalysis = {})
86 dimCtrl, eps, maxIt, /*lambda*/ 1., maxStepAttempts, stepCondition, verboseOn,
87 fname, logFileName, withUpperBound, upperBound,
88 withLowerBound, lowerBound, vectorBounds, controlEps, failOnMaxIter, gplotAnalysis),
89 clout(std::cout,"OptimizerLBFGS")
90 {
91 // Starting lambda for iT==0: steepest descent
92 // Line Search will be initialised with the natural lambda = 1
93 _startLambda = lambda;
94
95 _l=l;
96 _startCoefH = startCoefH;
97 _firstStore = 1;
98 _lastStore = 1;
99
100 _lastControl = util::ContainerCreator<C>::create(this->_dimCtrl);
101 _lastDerivative = util::ContainerCreator<C>::create(this->_dimCtrl);
102
103 _sStore = new S* [_l];
104 _yStore = new S* [_l];
105
106 _rhoStore = new S [_l];
107 _alpha = new S [_l];
108
109 for (int i=0; i<_l; i++) {
110 _rhoStore[i] = S(0);
111 _alpha[i] = S(0);
112 }
113
114 for (int i=0; i<_l; i++) {
115 _sStore[i] = new S [this->_dimCtrl];
116 _yStore[i] = new S [this->_dimCtrl];
117 //for (int iDim=0; iDim<this->_dimCtrl; ++iDim) {
118 //_sStore[i][iDim] = S(0);
119 //_yStore[i][iDim] = S(0);
120 //};
121 }
122 };
123
125 {
126 for (int i=0; i<_l; i++) {
127 delete[] _sStore[i];
128 delete[] _yStore[i];
129 }
130 delete[] _sStore;
131 delete[] _yStore;
132 delete[] _rhoStore;
133 delete[] _alpha;
134 }
135
136
137 void setL(int l)
138 {
139 _l=l;
140 };
141
142 void setStartCoefH( S startCoefH)
143 {
144 _startCoefH = startCoefH;
145 };
146
148 {
149 S normDir = util::euklidN(this->_direction.data(), this->_dimCtrl);
150 if (std::isnan(normDir)) {
151 clout << "Warning: Derivative is null at first iteration. Check derivative calculations.\nProgram terminated" << std::endl;
152 exit(1);
153 }
154 }
155
157 {
158
159 if (this->_it!=0) {
160 _rhoStore[(this->_it)%_l] = 0;
161 S temp1 = S();
162 S temp2 = S();
163 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
164 _sStore[(this->_it)%_l][iDim] = this->_control[iDim]-_lastControl[iDim];
165 _yStore[(this->_it)%_l][iDim] = this->_derivative[iDim]-_lastDerivative[iDim];
166 _rhoStore[(this->_it)%_l] += _yStore[(this->_it)%_l][iDim]*_sStore[(this->_it)%_l][iDim];
167 temp1 += _sStore[(this->_it)%_l][iDim]*_yStore[(this->_it)%_l][iDim];
168 temp2 += _yStore[(this->_it)%_l][iDim]*_yStore[(this->_it)%_l][iDim];
169 }
170 _startCoefH = temp1/temp2;
171
172 _rhoStore[(this->_it)%_l] = 1./_rhoStore[(this->_it)%_l];
173 if (this->_it>_l) {
174 _firstStore = (_firstStore+1)%_l;
175 }
176 _lastStore = (this->_it)%_l;
177 }
178
179 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
180 _lastControl[iDim] = this->_control[iDim];
181 _lastDerivative[iDim] = this->_derivative[iDim];
182 }
183 }
184
185 virtual void computeDirection()
186 {
187
188 // Update _derivative
189 // computeDerivative only if not already done by wolfeCondition()
190 if (!this->_nextDerivFlag) {
191 this->computeDerivatives(this->_control, this->_derivative);
192 }
193 else for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
194 this->_derivative[iDim] = this->_nextDerivative[iDim];
195 }
196
197 if (this->_it==0) {
198 // On first step do normalised steepest descent
199 S normDerivative = util::euklidN(this->_derivative.data(), this->_dimCtrl);
200 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
201 this->_direction[iDim] = _startLambda * this->_derivative[iDim] / normDerivative;
202 }
203 // terminate early if we recieve nan controls
205
206 // Store Helpers!
207 storeHelpers();
208
209 }
210 else {
211 storeHelpers();
212
213 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
214 this->_direction[iDim] = this->_derivative[iDim];
215 }
216
217 int iMax = _l;
218 if (this->_it<_l) {
219 iMax = this->_it;
220 }
221
222 int iStore;
223 // first for loop
224 for (int i=0; i<iMax; i++) {
225 iStore = (_lastStore + _l - i) % _l;
226
227 _alpha[iStore] = 0;
228 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
229 _alpha[iStore] += _sStore[iStore][iDim]*this->_direction[iDim];
230 }
231 _alpha[iStore] *= _rhoStore[iStore];
232
233 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
234 this->_direction[iDim] -= _alpha[iStore]*_yStore[iStore][iDim];
235 }
236 } // end first for loop
237 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
238 this->_direction[iDim] *= _startCoefH;
239 }
240
241 // second for loop
242 for (int i=0; i<iMax; i++) {
243 iStore = (_firstStore + _l + i) % _l;
244
245 S beta = 0;
246 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
247 beta += _yStore[iStore][iDim]*this->_direction[iDim];
248 }
249 beta *= _rhoStore[iStore];
250
251 for (int iDim=0; iDim<this->_dimCtrl; iDim++) {
252 this->_direction[iDim] += _sStore[iStore][iDim]*(_alpha[iStore]-beta);
253 }
254 } // end second for loop
255 }
256 };
257};
258
259
260
262template<typename S, typename C = std::vector<S>>
263OptimizerLBFGS<S,C>* createOptimizerLBFGS(XMLreader const& params, std::size_t dimCtrl)
264{
265 OstreamManager clout(std::cout, "createOptimizerLBFGS");
266
267 // create variables with default values
268 int maxIt = 100;
269 int l = 20;
270 S lambda = 1.; //starting lambda for steepest descent step (it==0)
271 int maxStepAttempts = 100;
272 std::string stepCondition = "StrongWolfe";
273
274 //S controlEps = S(std::numeric_limits<double>::epsilon() );
275 S controlEps = S(0);
276 S eps = S(1.e-10);
277 S startCoefH = S(1e-4);
278
279 bool verboseOn=true;
280 std::string fname = "control.dat";
281 std::string logFileName = "log.txt";
282 bool vectorBounds = false;
283 bool withUpperBound = false;
284 S upperBound = S();
285 bool withLowerBound = false;
286 S lowerBound = S();
287 bool failOnMaxIter = true;
288
289 std::vector<OptimizerLogType> gplotAnalysis = {};
290 std::string gplotAnalysisString = "";
291
292 // Read Values from XML File from area "Optimization"
293 params.readOrWarn<int>("Optimization", "MaxIter", "", maxIt);
294 params.readOrWarn<int>("Optimization", "L", "", l);
295 params.readOrWarn<S>("Optimization", "Lambda", "", lambda);
296 params.readOrWarn<int>("Optimization", "MaxStepAttempts", "", maxStepAttempts);
297 params.readOrWarn<std::string>("Optimization", "StepCondition", "", stepCondition);
298
299 params.readOrWarn<S>("Optimization", "Tolerance", "", eps);
300 params.readOrWarn<S>("Optimization", "ControlTolerance", "", controlEps);
301 params.readOrWarn<S>("Optimization", "StartCoefH", "", startCoefH);
302 params.readOrWarn<bool>("Optimization", "FailOnMaxIter", "", failOnMaxIter);
303 params.readOrWarn<bool>("Optimization", "Verbose", "", verboseOn);
304 params.readOrWarn<std::string>("Optimization", "InputFileName", "", fname);
305 params.readOrWarn<std::string>("Optimization", "LogFileName", "", logFileName);
306
307 params.readOrWarn<bool>("Optimization", "VectorBounds", "", vectorBounds);
308 if ( params.readOrWarn<S>("Optimization", "UpperBound", "", upperBound, false, false) ) {
309 withUpperBound = true;
310 }
311
312 if ( params.readOrWarn<S>("Optimization", "LowerBound", "", lowerBound, false, false) ) {
313 withLowerBound = true;
314 }
315
316 // get the parameters for the gnuplot Analysis from the xml file from the VisualizationGnuplot area
317 params.readOrWarn<std::string>("Optimization",
318 "VisualizationGnuplot",
319 "VisualizedParameters", gplotAnalysisString, false, false);
320 // transform the data from the xml file to the enums needed for continueing
321 getGnuplotTagsFromString(gplotAnalysisString, gplotAnalysis);
322
323 clout << "Creating optimizer ..." << std::endl;
324 // Create Optimizer Object
325 return new OptimizerLBFGS<S,C>(dimCtrl, eps, maxIt, lambda, maxStepAttempts, stepCondition, l, startCoefH,
326 verboseOn, fname, logFileName, withUpperBound, upperBound, withLowerBound, lowerBound, vectorBounds,
327 controlEps, failOnMaxIter, gplotAnalysis);
328}
329
330
331} // namespace opti
332
333} // namespace olb
334
335#endif
class for marking output with some text
bool readOrWarn(std::string name_parameter_1, std::string name_parameter_2, std::string name_parameter_3, ParameterType &var, bool defaultAvailable=true, bool exitIfMissing=false, bool showWarning=true) const
This wrapper function reads the given parameter from the "type_parameter" and "name_parameter_1" or "...
Definition xmlReader.h:178
Optimization algorithm: LBFGS.
OptimizerLBFGS(int dimCtrl, S eps, int maxIt, S lambda, int maxStepAttempts, std::string stepCondition, int l, S startCoefH, bool verboseOn=true, const std::string fname="", const std::string logFileName="", bool withUpperBound=false, S upperBound=S(), bool withLowerBound=false, S lowerBound=S(), bool vectorBounds=false, S controlEps=S(std::numeric_limits< double >::epsilon()), bool failOnMaxIter=true, std::vector< OptimizerLogType > gplotAnalysis={})
virtual void computeDirection()
void setStartCoefH(S startCoefH)
Optimization algorithm: LineSearch.
int _it
Current iteration no.
Definition optimizer.h:73
C _derivative
Vector of derivatives of the object functional with respect to the controlled variables.
Definition optimizer.h:71
int _dimCtrl
Number of controlled variables.
Definition optimizer.h:63
C _control
Vector of controlled variables (size _dimCtrl)
Definition optimizer.h:65
void computeDerivatives(const C &control, C &derivatives)
Definition optimizer.h:144
void getGnuplotTagsFromString(std::string gplotAnalysisString, std::vector< OptimizerLogType > &gplotAnalysis)
the gplotAnalysisString is gained from the xml file and the function than separates and prepares it t...
Definition optimizer.hh:236
OptimizerLBFGS< S, C > * createOptimizerLBFGS(XMLreader const &params, std::size_t dimCtrl)
Creator Function for LBFGS.
T euklidN(const T x[], int dim)
Euclidean norm of an array.
Definition norm.h:60
Top level namespace for all of OpenLB.
Optimization Code.
Implements Euclidean norm for arrays.
The description of line search optimization algorithm – header file.
Creates a container of type C.