1 #include <gtest/gtest.h>
2 #include <stan/optimization/bfgs.hpp>
3 #include <test/test-models/good/optimization/rosenbrock.hpp>
4 #include <sstream>
5 
6 typedef rosenbrock_model_namespace::rosenbrock_model Model;
7 typedef stan::optimization::BFGSMinimizer<
8     stan::optimization::ModelAdaptor<Model>,
9     stan::optimization::BFGSUpdate_HInv<> >
10     Optimizer;
11 
12 class OptimizationBfgsMinimizer : public testing::Test {
13  public:
14   Eigen::Matrix<double, Eigen::Dynamic, 1> cont_vector;
15   std::vector<int> disc_vector;
16 
SetUp()17   void SetUp() {
18     cont_vector.resize(2);
19     cont_vector[0] = -1;
20     cont_vector[1] = 1;
21   }
22 };
23 
TEST_F(OptimizationBfgsMinimizer,constructor)24 TEST_F(OptimizationBfgsMinimizer, constructor) {
25   static const std::string DATA("");
26   std::stringstream data_stream(DATA);
27   stan::io::dump dummy_context(data_stream);
28   Model rb_model(dummy_context);
29   std::stringstream out;
30   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
31   EXPECT_EQ("", out.str());
32   Optimizer bfgs(_adaptor);
33 }
34 
TEST_F(OptimizationBfgsMinimizer,ls_opts)35 TEST_F(OptimizationBfgsMinimizer, ls_opts) {
36   static const std::string DATA("");
37   std::stringstream data_stream(DATA);
38   stan::io::dump dummy_context(data_stream);
39   Model rb_model(dummy_context);
40   std::stringstream out;
41   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
42   EXPECT_EQ("", out.str());
43   Optimizer bfgs(_adaptor);
44 
45   EXPECT_FLOAT_EQ(bfgs._ls_opts.c1, 1e-4);
46   EXPECT_FLOAT_EQ(bfgs._ls_opts.c2, 0.9);
47   EXPECT_FLOAT_EQ(bfgs._ls_opts.minAlpha, 1e-12);
48   EXPECT_FLOAT_EQ(bfgs._ls_opts.alpha0, 1e-3);
49 }
50 
TEST_F(OptimizationBfgsMinimizer,conv_opts)51 TEST_F(OptimizationBfgsMinimizer, conv_opts) {
52   static const std::string DATA("");
53   std::stringstream data_stream(DATA);
54   stan::io::dump dummy_context(data_stream);
55   Model rb_model(dummy_context);
56   std::stringstream out;
57   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
58   EXPECT_EQ("", out.str());
59   Optimizer bfgs(_adaptor);
60 
61   EXPECT_FLOAT_EQ(bfgs._conv_opts.maxIts, 10000);
62   EXPECT_FLOAT_EQ(bfgs._conv_opts.fScale, 1);
63   EXPECT_FLOAT_EQ(bfgs._conv_opts.tolAbsX, 1e-8);
64   EXPECT_FLOAT_EQ(bfgs._conv_opts.tolAbsF, 1e-12);
65   EXPECT_FLOAT_EQ(bfgs._conv_opts.tolAbsGrad, 1e-8);
66   EXPECT_FLOAT_EQ(bfgs._conv_opts.tolRelF, 1e+4);
67   EXPECT_FLOAT_EQ(bfgs._conv_opts.tolRelGrad, 1e+3);
68 }
69 
TEST_F(OptimizationBfgsMinimizer,get_qnupdate)70 TEST_F(OptimizationBfgsMinimizer, get_qnupdate) {
71   static const std::string DATA("");
72   std::stringstream data_stream(DATA);
73   stan::io::dump dummy_context(data_stream);
74   Model rb_model(dummy_context);
75   std::stringstream out;
76   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
77   EXPECT_EQ("", out.str());
78   Optimizer bfgs(_adaptor);
79   bfgs.initialize(cont_vector);
80 
81   bfgs.get_qnupdate();
82 }
83 
TEST_F(OptimizationBfgsMinimizer,curr_f)84 TEST_F(OptimizationBfgsMinimizer, curr_f) {
85   static const std::string DATA("");
86   std::stringstream data_stream(DATA);
87   stan::io::dump dummy_context(data_stream);
88   Model rb_model(dummy_context);
89   std::stringstream out;
90   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
91   EXPECT_EQ("", out.str());
92   Optimizer bfgs(_adaptor);
93   bfgs.initialize(cont_vector);
94 
95   EXPECT_FLOAT_EQ(bfgs.curr_f(), 4);
96 }
97 
TEST_F(OptimizationBfgsMinimizer,curr_x)98 TEST_F(OptimizationBfgsMinimizer, curr_x) {
99   static const std::string DATA("");
100   std::stringstream data_stream(DATA);
101   stan::io::dump dummy_context(data_stream);
102   Model rb_model(dummy_context);
103   std::stringstream out;
104   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
105   EXPECT_EQ("", out.str());
106   Optimizer bfgs(_adaptor);
107   bfgs.initialize(cont_vector);
108 
109   EXPECT_FLOAT_EQ(bfgs.curr_x()[0], -1);
110   EXPECT_FLOAT_EQ(bfgs.curr_x()[1], 1);
111 }
112 
TEST_F(OptimizationBfgsMinimizer,curr_g)113 TEST_F(OptimizationBfgsMinimizer, curr_g) {
114   static const std::string DATA("");
115   std::stringstream data_stream(DATA);
116   stan::io::dump dummy_context(data_stream);
117   Model rb_model(dummy_context);
118   std::stringstream out;
119   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
120   EXPECT_EQ("", out.str());
121   Optimizer bfgs(_adaptor);
122   bfgs.initialize(cont_vector);
123 
124   EXPECT_FLOAT_EQ(bfgs.curr_g()[0], -4);
125   EXPECT_FLOAT_EQ(bfgs.curr_g()[1], 0);
126 }
127 
TEST_F(OptimizationBfgsMinimizer,curr_p)128 TEST_F(OptimizationBfgsMinimizer, curr_p) {
129   static const std::string DATA("");
130   std::stringstream data_stream(DATA);
131   stan::io::dump dummy_context(data_stream);
132   Model rb_model(dummy_context);
133   std::stringstream out;
134   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
135   EXPECT_EQ("", out.str());
136   Optimizer bfgs(_adaptor);
137   bfgs.initialize(cont_vector);
138 
139   EXPECT_FLOAT_EQ(bfgs.curr_p()[0], 4);
140   EXPECT_FLOAT_EQ(bfgs.curr_p()[1], 0);
141 }
142 
TEST_F(OptimizationBfgsMinimizer,prev_f)143 TEST_F(OptimizationBfgsMinimizer, prev_f) {
144   static const std::string DATA("");
145   std::stringstream data_stream(DATA);
146   stan::io::dump dummy_context(data_stream);
147   Model rb_model(dummy_context);
148   std::stringstream out;
149   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
150   EXPECT_EQ("", out.str());
151   Optimizer bfgs(_adaptor);
152   bfgs.initialize(cont_vector);
153 
154   bfgs.step();
155   EXPECT_FLOAT_EQ(bfgs.prev_f(), 4);
156 }
157 
TEST_F(OptimizationBfgsMinimizer,prev_x)158 TEST_F(OptimizationBfgsMinimizer, prev_x) {
159   static const std::string DATA("");
160   std::stringstream data_stream(DATA);
161   stan::io::dump dummy_context(data_stream);
162   Model rb_model(dummy_context);
163   std::stringstream out;
164   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
165   EXPECT_EQ("", out.str());
166   Optimizer bfgs(_adaptor);
167   bfgs.initialize(cont_vector);
168 
169   bfgs.step();
170   EXPECT_FLOAT_EQ(bfgs.prev_x()[0], -1);
171   EXPECT_FLOAT_EQ(bfgs.prev_x()[1], 1);
172 }
173 
TEST_F(OptimizationBfgsMinimizer,prev_g)174 TEST_F(OptimizationBfgsMinimizer, prev_g) {
175   static const std::string DATA("");
176   std::stringstream data_stream(DATA);
177   stan::io::dump dummy_context(data_stream);
178   Model rb_model(dummy_context);
179   std::stringstream out;
180   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
181   EXPECT_EQ("", out.str());
182   Optimizer bfgs(_adaptor);
183   bfgs.initialize(cont_vector);
184 
185   bfgs.step();
186   EXPECT_FLOAT_EQ(bfgs.prev_g()[0], -4);
187   EXPECT_FLOAT_EQ(bfgs.prev_g()[1], 0);
188 }
189 
TEST_F(OptimizationBfgsMinimizer,prev_p)190 TEST_F(OptimizationBfgsMinimizer, prev_p) {
191   static const std::string DATA("");
192   std::stringstream data_stream(DATA);
193   stan::io::dump dummy_context(data_stream);
194   Model rb_model(dummy_context);
195   std::stringstream out;
196   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
197   EXPECT_EQ("", out.str());
198   Optimizer bfgs(_adaptor);
199   bfgs.initialize(cont_vector);
200 
201   bfgs.step();
202   EXPECT_FLOAT_EQ(bfgs.prev_p()[0], 0.0040116129);
203   EXPECT_FLOAT_EQ(bfgs.prev_p()[1], 0);
204 }
205 
TEST_F(OptimizationBfgsMinimizer,prev_step_size)206 TEST_F(OptimizationBfgsMinimizer, prev_step_size) {
207   static const std::string DATA("");
208   std::stringstream data_stream(DATA);
209   stan::io::dump dummy_context(data_stream);
210   Model rb_model(dummy_context);
211   std::stringstream out;
212   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
213   EXPECT_EQ("", out.str());
214   Optimizer bfgs(_adaptor);
215   bfgs.initialize(cont_vector);
216 
217   bfgs.step();
218   EXPECT_FLOAT_EQ(bfgs.prev_step_size(), 0.0040000002);
219 }
220 
TEST_F(OptimizationBfgsMinimizer,rel_grad_norm)221 TEST_F(OptimizationBfgsMinimizer, rel_grad_norm) {
222   static const std::string DATA("");
223   std::stringstream data_stream(DATA);
224   stan::io::dump dummy_context(data_stream);
225   Model rb_model(dummy_context);
226   std::stringstream out;
227   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
228   EXPECT_EQ("", out.str());
229   Optimizer bfgs(_adaptor);
230   bfgs.initialize(cont_vector);
231 
232   bfgs.step();
233   EXPECT_FLOAT_EQ(bfgs.rel_grad_norm(), 0.0012151747);
234 }
235 
TEST_F(OptimizationBfgsMinimizer,rel_obj_decrease)236 TEST_F(OptimizationBfgsMinimizer, rel_obj_decrease) {
237   static const std::string DATA("");
238   std::stringstream data_stream(DATA);
239   stan::io::dump dummy_context(data_stream);
240   Model rb_model(dummy_context);
241   std::stringstream out;
242   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
243   EXPECT_EQ("", out.str());
244   Optimizer bfgs(_adaptor);
245   bfgs.initialize(cont_vector);
246 
247   bfgs.step();
248   EXPECT_FLOAT_EQ(bfgs.rel_obj_decrease(), 0.0024023936);
249 }
250 
TEST_F(OptimizationBfgsMinimizer,alpha0)251 TEST_F(OptimizationBfgsMinimizer, alpha0) {
252   static const std::string DATA("");
253   std::stringstream data_stream(DATA);
254   stan::io::dump dummy_context(data_stream);
255   Model rb_model(dummy_context);
256   std::stringstream out;
257   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
258   EXPECT_EQ("", out.str());
259   Optimizer bfgs(_adaptor);
260   bfgs.initialize(cont_vector);
261 
262   bfgs.step();
263   EXPECT_FLOAT_EQ(bfgs.alpha0(), 0.001);
264 }
265 
TEST_F(OptimizationBfgsMinimizer,alpha)266 TEST_F(OptimizationBfgsMinimizer, alpha) {
267   static const std::string DATA("");
268   std::stringstream data_stream(DATA);
269   stan::io::dump dummy_context(data_stream);
270   Model rb_model(dummy_context);
271   std::stringstream out;
272   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
273   EXPECT_EQ("", out.str());
274   Optimizer bfgs(_adaptor);
275   bfgs.initialize(cont_vector);
276 
277   bfgs.step();
278   EXPECT_FLOAT_EQ(bfgs.alpha(), 0.001);
279 }
280 
TEST_F(OptimizationBfgsMinimizer,iter_num)281 TEST_F(OptimizationBfgsMinimizer, iter_num) {
282   static const std::string DATA("");
283   std::stringstream data_stream(DATA);
284   stan::io::dump dummy_context(data_stream);
285   Model rb_model(dummy_context);
286   std::stringstream out;
287   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
288   EXPECT_EQ("", out.str());
289   Optimizer bfgs(_adaptor);
290   bfgs.initialize(cont_vector);
291 
292   EXPECT_FLOAT_EQ(bfgs.iter_num(), 0);
293   bfgs.step();
294   EXPECT_FLOAT_EQ(bfgs.iter_num(), 1);
295 }
296 
TEST_F(OptimizationBfgsMinimizer,note)297 TEST_F(OptimizationBfgsMinimizer, note) {
298   static const std::string DATA("");
299   std::stringstream data_stream(DATA);
300   stan::io::dump dummy_context(data_stream);
301   Model rb_model(dummy_context);
302   std::stringstream out;
303   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
304   EXPECT_EQ("", out.str());
305   Optimizer bfgs(_adaptor);
306   bfgs.initialize(cont_vector);
307 
308   bfgs.step();
309   EXPECT_TRUE(bfgs.note() == "");
310 }
311 
TEST_F(OptimizationBfgsMinimizer,get_code_string)312 TEST_F(OptimizationBfgsMinimizer, get_code_string) {
313   static const std::string DATA("");
314   std::stringstream data_stream(DATA);
315   stan::io::dump dummy_context(data_stream);
316   Model rb_model(dummy_context);
317   std::stringstream out;
318   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
319   EXPECT_EQ("", out.str());
320   Optimizer bfgs(_adaptor);
321   bfgs.initialize(cont_vector);
322 
323   EXPECT_TRUE(bfgs.get_code_string(0) == "Successful step completed");
324   EXPECT_TRUE(
325       bfgs.get_code_string(10)
326       == "Convergence detected: absolute parameter change was below tolerance");
327   EXPECT_TRUE(bfgs.get_code_string(20) == "Convergence detected: absolute change in objective function was below tolerance");
328   EXPECT_TRUE(bfgs.get_code_string(21) == "Convergence detected: relative change in objective function was below tolerance");
329   EXPECT_TRUE(bfgs.get_code_string(30)
330               == "Convergence detected: gradient norm is below tolerance");
331   EXPECT_TRUE(
332       bfgs.get_code_string(31)
333       == "Convergence detected: relative gradient magnitude is below "
334          "tolerance");
335   EXPECT_TRUE(bfgs.get_code_string(40)
336               == "Maximum number of iterations hit, may not be at an optima");
337   EXPECT_TRUE(bfgs.get_code_string(-1) == "Line search failed to achieve a sufficient decrease, no more progress can be made");
338   EXPECT_TRUE(bfgs.get_code_string(42) == "Unknown termination code");
339   EXPECT_TRUE(bfgs.get_code_string(32) == "Unknown termination code");
340   EXPECT_TRUE(bfgs.get_code_string(23) == "Unknown termination code");
341   EXPECT_TRUE(bfgs.get_code_string(94) == "Unknown termination code");
342 }
343 
TEST_F(OptimizationBfgsMinimizer,initialize)344 TEST_F(OptimizationBfgsMinimizer, initialize) {
345   static const std::string DATA("");
346   std::stringstream data_stream(DATA);
347   stan::io::dump dummy_context(data_stream);
348   Model rb_model(dummy_context);
349   std::stringstream out;
350   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
351   EXPECT_EQ("", out.str());
352   Optimizer bfgs(_adaptor);
353 
354   EXPECT_FLOAT_EQ(bfgs.curr_x().size(), 0);
355   EXPECT_FLOAT_EQ(bfgs.curr_p().size(), 0);
356   EXPECT_FLOAT_EQ(bfgs.curr_g().size(), 0);
357 
358   bfgs.initialize(cont_vector);
359   EXPECT_FLOAT_EQ(bfgs.curr_x().size(), 2);
360   EXPECT_FLOAT_EQ(bfgs.curr_x()[0], -1);
361   EXPECT_FLOAT_EQ(bfgs.curr_x()[1], 1);
362   EXPECT_FLOAT_EQ(bfgs.curr_p().size(), 2);
363   EXPECT_FLOAT_EQ(bfgs.curr_p()[0], 4);
364   EXPECT_FLOAT_EQ(bfgs.curr_p()[1], 0);
365   EXPECT_FLOAT_EQ(bfgs.curr_g().size(), 2);
366   EXPECT_FLOAT_EQ(bfgs.curr_g()[0], -4);
367   EXPECT_FLOAT_EQ(bfgs.curr_g()[1], 0);
368   EXPECT_FLOAT_EQ(bfgs.iter_num(), 0);
369   EXPECT_TRUE(bfgs.note() == "");
370 }
371 
TEST_F(OptimizationBfgsMinimizer,step)372 TEST_F(OptimizationBfgsMinimizer, step) {
373   static const std::string DATA("");
374   std::stringstream data_stream(DATA);
375   stan::io::dump dummy_context(data_stream);
376   Model rb_model(dummy_context);
377   std::stringstream out;
378   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
379   EXPECT_EQ("", out.str());
380   Optimizer bfgs(_adaptor);
381   bfgs.initialize(cont_vector);
382   bfgs.step();
383 }
384 
TEST_F(OptimizationBfgsMinimizer,minimize)385 TEST_F(OptimizationBfgsMinimizer, minimize) {
386   static const std::string DATA("");
387   std::stringstream data_stream(DATA);
388   stan::io::dump dummy_context(data_stream);
389   Model rb_model(dummy_context);
390   std::stringstream out;
391   stan::optimization::ModelAdaptor<Model> _adaptor(rb_model, disc_vector, &out);
392   EXPECT_EQ("", out.str());
393   Optimizer bfgs(_adaptor);
394 
395   EXPECT_FLOAT_EQ(bfgs.minimize(cont_vector), 31);
396 }
397