test_levenberg_marquardt_sparse.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2017,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This software is currently not released.
10  * Redistribution and use in source and binary forms,
11  * with or without modification, are prohibited.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  * Authors: Christoph Rösmann
27  *********************************************************************/
28 
30 
31 #include <corbo-optimization/standard_optimization_problem.h>
32 
33 #include <corbo-core/console.h>
34 #include <corbo-core/macros.h>
35 #include <corbo-core/utilities.h>
37 
38 #include <array>
39 #include <functional>
40 
41 #include "gtest/gtest.h"
42 
44 using corbo::StandardOptimizationProblemWithCallbacks;
45 
46 class TestLevenbergMarquardtSparse : public testing::Test
47 {
48  protected:
49  // You can do set-up work for each test here.
51  // You can do clean-up work that doesn't throw exceptions here.
53  // If the constructor and destructor are not enough for setting up
54  // and cleaning up each test, you can define the following methods:
55 
56  // Code here will be called immediately after the constructor (right
57  // before each test).
58  void SetUp() override
59  {
60  // configure solver
61  solver.setIterations(100);
62  }
63  // Code here will be called immediately after each test (right
64  // before the destructor).
65  // virtual void TearDown()
66 
67  StandardOptimizationProblemWithCallbacks optim;
68 
70 };
71 
73 {
74  // parameters
75  optim.resizeParameterVector(1);
76  Eigen::VectorXd x(1);
77  x.setOnes();
78  optim.setX(x);
79 
80  // create objective function
81  // (x-2)^2
82  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 2; };
83  optim.setObjectiveFunction(objective, 1, true); // least-squares type
84 
85  EXPECT_TRUE(solver.initialize(optim));
86 
87  bool success = solver.solve(optim, true);
88 
89  EXPECT_TRUE(success);
90  EXPECT_NEAR(optim.getX()[0], 2.0, 1e-6);
91 }
92 
94 {
95  // parameters
96  optim.resizeParameterVector(3);
97  Eigen::VectorXd x(3);
98  x.setOnes();
99  optim.setX(x);
100 
101  // create objective function
102  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
103  values[0] = x[0] - 5;
104  values[1] = x[1] + 3;
105  values[2] = x[2];
106  };
107  optim.setObjectiveFunction(objective, 3, true); // least-squares type
108 
109  EXPECT_TRUE(solver.initialize(optim));
110 
111  bool success = solver.solve(optim, true);
112 
113  EXPECT_TRUE(success);
114  EXPECT_NEAR(optim.getX()[0], 5.0, 1e-6);
115  EXPECT_NEAR(optim.getX()[1], -3.0, 1e-6);
116  EXPECT_NEAR(optim.getX()[2], 0.0, 1e-6);
117 }
118 
119 TEST_F(TestLevenbergMarquardtSparse, solve_rosenbrock_unconstr)
120 {
121  // parameters
122  optim.resizeParameterVector(2);
123  Eigen::VectorXd x(2);
124  x.setOnes();
125  optim.setX(x);
126 
127  // create objective function
128  // Create edges for minimizing 0.5 * (100*(x2-x1^2)^2 + (1-x1)^2 ) => f1^2 + f2^2
129  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
130  values[0] = std::sqrt(100) * (x[1] - x[0] * x[0]);
131  values[1] = 1 - x[0];
132  };
133  optim.setObjectiveFunction(objective, 2, true); // least-squares type
134 
135  EXPECT_TRUE(solver.initialize(optim));
136 
137  // now solve
138  bool success = solver.solve(optim, true);
139 
140  EXPECT_TRUE(success);
141  EXPECT_NEAR(optim.getX()[0], 1.0, 1e-3);
142  EXPECT_NEAR(optim.getX()[1], 1.0, 1e-3);
143 }
144 
146 {
147  // parameters
148  optim.resizeParameterVector(1);
149  Eigen::VectorXd x(1);
150  x.setOnes();
151  optim.setX(x);
152 
153  // create objective function
154  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 2; };
155  optim.setObjectiveFunction(objective, 1, true); // least-squares type
156 
157  // create equality constraint function
158  auto equality = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 3; };
159  optim.setEqualityConstraint(equality, 1);
160 
161  solver.setPenaltyWeights(100, 100, 100);
162 
163  EXPECT_TRUE(solver.initialize(optim));
164 
165  bool success = solver.solve(optim, true);
166 
167  EXPECT_TRUE(success);
168  EXPECT_NEAR(optim.getX()[0], 3.0, 1e-4);
169 }
170 
172 {
173  // parameters
174  optim.resizeParameterVector(1);
175  Eigen::VectorXd x(1);
176  x.setOnes();
177  optim.setX(x);
178 
179  // create objective function
180  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 2; }; // min -> x = 2
181  optim.setObjectiveFunction(objective, 1, true); // least-squares type
182 
183  // create inequality constraint function
184  auto inequality = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = -x[0] + 3; }; // x > 3
185  optim.setInequalityConstraint(inequality, 1);
186 
187  solver.setPenaltyWeights(100, 100, 100);
188 
189  EXPECT_TRUE(solver.initialize(optim));
190 
191  bool success = solver.solve(optim, true);
192 
193  EXPECT_TRUE(success);
194  EXPECT_NEAR(optim.getX()[0], 3.0, 1e-4);
195 }
196 
198 {
199  // parameters
200  optim.resizeParameterVector(1);
201  Eigen::VectorXd x(1);
202  x.setOnes();
203  optim.setX(x);
204 
205  // set bounds
206  Eigen::VectorXd lb(1);
207  lb[0] = 5;
208  optim.setLowerBounds(lb);
209 
210  // create objective function
211  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 2; }; // min -> x = 2
212  optim.setObjectiveFunction(objective, 1, true); // least-squares type
213 
214  solver.setPenaltyWeights(100, 100, 100);
215 
216  EXPECT_TRUE(solver.initialize(optim));
217 
218  bool success = solver.solve(optim, true);
219 
220  EXPECT_TRUE(success);
221  EXPECT_NEAR(optim.getX()[0], 5.0, 1e-3);
222 }
223 
225 {
226  // parameters
227  optim.resizeParameterVector(1);
228  Eigen::VectorXd x(1);
229  x.setOnes();
230  optim.setX(x);
231 
232  // set bounds
233  Eigen::VectorXd ub(1);
234  ub[0] = -1;
235  optim.setUpperBounds(ub);
236 
237  // create objective function
238  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) { values[0] = x[0] - 2; }; // min -> x = 2
239  optim.setObjectiveFunction(objective, 1, true); // least-squares type
240 
241  solver.setPenaltyWeights(100, 100, 100);
242 
243  EXPECT_TRUE(solver.initialize(optim));
244 
245  bool success = solver.solve(optim, true);
246 
247  EXPECT_TRUE(success);
248  EXPECT_NEAR(optim.getX()[0], -1.0, 1e-3);
249 }
250 
251 TEST_F(TestLevenbergMarquardtSparse, solve_betts_fun_constr)
252 {
253  // parameters
254  optim.resizeParameterVector(2);
255 
256  // create bounds on x1 and x2
257  optim.setLowerBound(0, 2);
258  optim.setUpperBound(0, 50);
259  optim.setLowerBound(1, -50);
260  optim.setUpperBound(1, 50);
261 
262  // Problem definition
263  // min 0.01 * x1^2 + x2^2 - 100
264  // s.t. 2<=x1<=50,
265  // -50<=x2<=50,
266  // 10*x1-x2>=10
267 
268  // Create objective for minimizing
269  // 0.01 * x1^2 + x2^2 - 100 = f1^2 + f^2
270  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
271  values[0] = std::sqrt(0.01) * x[0];
272  values[1] = x[1];
273  };
274  optim.setObjectiveFunction(objective, 2, true); // least-squares type
275 
276  // Create inequality for satisfying
277  // 10*x1-x2>=10 -> 10*x1-x2-10>=0 -> x2-10*x1+10<=0
278  auto inequality = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
279  values[0] = x[1] - 10.0 * x[0] + 10.0; // c(x)<=0 convention
280  };
281  optim.setInequalityConstraint(inequality, 1);
282 
283  // feasible start
284  optim.setParameterValue(0, 5);
285  optim.setParameterValue(0, -5);
286 
287  // now solve
288  bool success = solver.solve(optim, true);
289 
290  EXPECT_TRUE(success);
291  EXPECT_NEAR(optim.getX()[0], 2.0, 1e-2);
292  EXPECT_NEAR(optim.getX()[1], 0.0, 1e-2);
293 
294  // infeasible start
295  optim.setParameterValue(0, -1);
296  optim.setParameterValue(0, -1);
297 
298  solver.setPenaltyWeights(1, 10, 10);
299  solver.setIterations(5000);
300  EXPECT_TRUE(solver.initialize(optim));
301 
302  // now solve
303  success = solver.solve(optim, true);
304 
305  EXPECT_TRUE(success);
306  EXPECT_NEAR(optim.getX()[0], 2.0, 1e-2);
307  EXPECT_NEAR(optim.getX()[1], 0.0, 1e-2);
308 }
309 
310 TEST_F(TestLevenbergMarquardtSparse, solve_betts_fun_constr_weight_adapt)
311 {
312  // parameters
313  optim.resizeParameterVector(2);
314 
315  // create bounds on x1 and x2
316  optim.setLowerBound(0, 2);
317  optim.setUpperBound(0, 50);
318  optim.setLowerBound(1, -50);
319  optim.setUpperBound(1, 50);
320 
321  // Problem definition
322  // min 0.01 * x1^2 + x2^2 - 100
323  // s.t. 2<=x1<=50,
324  // -50<=x2<=50,
325  // 10*x1-x2>=10
326 
327  // Create objective for minimizing
328  // 0.01 * x1^2 + x2^2 - 100 = f1^2 + f^2
329  auto objective = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
330  values[0] = std::sqrt(0.01) * x[0];
331  values[1] = x[1];
332  };
333  optim.setObjectiveFunction(objective, 2, true); // least-squares type
334 
335  // Create inequality for satisfying
336  // 10*x1-x2>=10 -> 10*x1-x2-10>=0 -> x2-10*x1+10<=0
337  auto inequality = [](const Eigen::VectorXd& x, Eigen::Ref<Eigen::VectorXd> values) {
338  values[0] = x[1] - 10.0 * x[0] + 10.0; // c(x)<=0 convention
339  };
340  optim.setInequalityConstraint(inequality, 1);
341 
342  // feasible start
343  optim.setParameterValue(0, 5);
344  optim.setParameterValue(0, -5);
345 
346  // set weight adaptation
347  solver.setPenaltyWeights(2, 2, 2);
348  solver.setWeightAdapation(5, 5, 5, 500, 500, 500);
349  solver.setIterations(5);
350 
351  EXPECT_TRUE(solver.initialize(optim));
352 
353  // now solve
354  bool success;
355  for (int i = 0; i < 5; ++i) success = solver.solve(optim, true, i == 0 ? true : false);
356 
357  EXPECT_TRUE(success);
358  EXPECT_NEAR(optim.getX()[0], 2.0, 1e-2);
359  EXPECT_NEAR(optim.getX()[1], 0.0, 1e-2);
360 
361  // infeasible start
362  optim.setParameterValue(0, -1);
363  optim.setParameterValue(0, -1);
364 
365  // now solve
366  for (int i = 0; i < 5; ++i) success = solver.solve(optim, true, i == 0 ? true : false);
367 
368  EXPECT_TRUE(success);
369  EXPECT_NEAR(optim.getX()[0], 2.0, 1e-2);
370  EXPECT_NEAR(optim.getX()[1], 0.0, 1e-2);
371 }
sqrt
const EIGEN_DEVICE_FUNC SqrtReturnType sqrt() const
Definition: ArrayCwiseUnaryOps.h:152
corbo::LevenbergMarquardtSparse
Levenberg-Marquardt Solver (Sparse matrices version).
Definition: levenberg_marquardt_sparse.h:90
levenberg_marquardt_sparse.h
macros.h
console.h
utilities.h
value_comparison.h
TestLevenbergMarquardtSparse::solver
LevenbergMarquardtSparse solver
Definition: test_levenberg_marquardt_sparse.cpp:69
TestLevenbergMarquardtSparse
Definition: test_levenberg_marquardt_sparse.cpp:46
TEST_F
TEST_F(TestLevenbergMarquardtSparse, solve_unconstr_1)
Definition: test_levenberg_marquardt_sparse.cpp:72
corbo::LevenbergMarquardtSparse::setIterations
void setIterations(int iterations)
Define the number of solver iterations.
Definition: levenberg_marquardt_sparse.h:130
TestLevenbergMarquardtSparse::SetUp
void SetUp() override
Definition: test_levenberg_marquardt_sparse.cpp:58
TestLevenbergMarquardtSparse::~TestLevenbergMarquardtSparse
virtual ~TestLevenbergMarquardtSparse()
Definition: test_levenberg_marquardt_sparse.cpp:52
x
Scalar * x
Definition: level1_cplx_impl.h:89
Eigen::Ref
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:192
TestLevenbergMarquardtSparse::TestLevenbergMarquardtSparse
TestLevenbergMarquardtSparse()
Definition: test_levenberg_marquardt_sparse.cpp:50
TestLevenbergMarquardtSparse::optim
StandardOptimizationProblemWithCallbacks optim
Definition: test_levenberg_marquardt_sparse.cpp:67


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Wed Mar 2 2022 00:07:06