GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tests/eiquadprog-basic.cpp Lines: 234 234 100.0 %
Date: 2021-03-10 23:02:29 Branches: 682 1364 50.0 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2019 CNRS
3
//
4
// This file is part of eiquadprog.
5
//
6
// eiquadprog is free software: you can redistribute it and/or modify
7
// it under the terms of the GNU Lesser General Public License as published by
8
// the Free Software Foundation, either version 3 of the License, or
9
//(at your option) any later version.
10
11
// eiquadprog is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU Lesser General Public License for more details.
15
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with eiquadprog.  If not, see <https://www.gnu.org/licenses/>.
18
19
#include <iostream>
20
21
#include <Eigen/Core>
22
23
#include <boost/test/unit_test.hpp>
24
25
#include "eiquadprog/eiquadprog.hpp"
26
27
// The problem is in the form:
28
// min 0.5 * x G x + g0 x
29
// s.t.
30
// CE^T x + ce0 = 0
31
// CI^T x + ci0 >= 0
32
// The matrix and vectors dimensions are as follows:
33
// G: n * n
34
// g0: n
35
// CE: n * p
36
// ce0: p
37
// CI: n * m
38
// ci0: m
39
// x: n
40
41

1
BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
42
43
// min ||x||^2
44
45


















3
BOOST_AUTO_TEST_CASE(test_unbiased) {
46
2
  Eigen::MatrixXd Q(2, 2);
47
1
  Q.setZero();
48
1
  Q(0, 0) = 1.0;
49
1
  Q(1, 1) = 1.0;
50
51
2
  Eigen::VectorXd C(2);
52
1
  C.setZero();
53
54
2
  Eigen::MatrixXd Aeq(2, 0);
55
56
2
  Eigen::VectorXd Beq(0);
57
58
2
  Eigen::MatrixXd Aineq(2, 0);
59
60
2
  Eigen::VectorXd Bineq(0);
61
62
2
  Eigen::VectorXd x(2);
63
2
  Eigen::VectorXi activeSet(0);
64
  size_t activeSetSize;
65
66
2
  Eigen::VectorXd solution(2);
67
1
  solution.setZero();
68
69
1
  double val = 0.0;
70
71
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
72
73



1
  BOOST_CHECK_CLOSE(out, val, 1e-6);
74
75




3
  BOOST_CHECK(x.isApprox(solution));
76
1
}
77
78
// min ||x-x_0||^2, x_0 = (1 1)^T
79
80


















3
BOOST_AUTO_TEST_CASE(test_biased) {
81
2
  Eigen::MatrixXd Q(2, 2);
82
1
  Q.setZero();
83
1
  Q(0, 0) = 1.0;
84
1
  Q(1, 1) = 1.0;
85
86
2
  Eigen::VectorXd C(2);
87
1
  C(0) = -1.;
88
1
  C(1) = -1.;
89
90
2
  Eigen::MatrixXd Aeq(2, 0);
91
92
2
  Eigen::VectorXd Beq(0);
93
94
2
  Eigen::MatrixXd Aineq(2, 0);
95
96
2
  Eigen::VectorXd Bineq(0);
97
98
2
  Eigen::VectorXd x(2);
99
2
  Eigen::VectorXi activeSet(0);
100
  size_t activeSetSize;
101
102
2
  Eigen::VectorXd solution(2);
103
1
  solution(0) = 1.;
104
1
  solution(1) = 1.;
105
106
1
  double val = -1.;
107
108
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
109
110



1
  BOOST_CHECK_CLOSE(out, val, 1e-6);
111
112




3
  BOOST_CHECK(x.isApprox(solution));
113
1
}
114
115
// min ||x||^2
116
//    s.t.
117
// x[1] = 1 - x[0]
118
119


















3
BOOST_AUTO_TEST_CASE(test_equality_constraints) {
120
2
  Eigen::MatrixXd Q(2, 2);
121
1
  Q.setZero();
122
1
  Q(0, 0) = 1.0;
123
1
  Q(1, 1) = 1.0;
124
125
2
  Eigen::VectorXd C(2);
126
1
  C.setZero();
127
128
2
  Eigen::MatrixXd Aeq(2, 1);
129
1
  Aeq(0, 0) = 1.;
130
1
  Aeq(1, 0) = 1.;
131
132
2
  Eigen::VectorXd Beq(1);
133
1
  Beq(0) = -1.;
134
135
2
  Eigen::MatrixXd Aineq(2, 0);
136
137
2
  Eigen::VectorXd Bineq(0);
138
139
2
  Eigen::VectorXd x(2);
140
2
  Eigen::VectorXi activeSet(1);
141
  size_t activeSetSize;
142
143
2
  Eigen::VectorXd solution(2);
144
1
  solution(0) = 0.5;
145
1
  solution(1) = 0.5;
146
147
1
  double val = 0.25;
148
149
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
150
151



1
  BOOST_CHECK_CLOSE(out, val, 1e-6);
152
153




3
  BOOST_CHECK(x.isApprox(solution));
154
1
}
155
156
// min ||x||^2
157
//    s.t.
158
// x[i] >= 1
159
160


















3
BOOST_AUTO_TEST_CASE(test_inequality_constraints) {
161
2
  Eigen::MatrixXd Q(2, 2);
162
1
  Q.setZero();
163
1
  Q(0, 0) = 1.0;
164
1
  Q(1, 1) = 1.0;
165
166
2
  Eigen::VectorXd C(2);
167
1
  C.setZero();
168
169
2
  Eigen::MatrixXd Aeq(2, 0);
170
171
2
  Eigen::VectorXd Beq(0);
172
173
2
  Eigen::MatrixXd Aineq(2, 2);
174
1
  Aineq.setZero();
175
1
  Aineq(0, 0) = 1.;
176
1
  Aineq(1, 1) = 1.;
177
178
2
  Eigen::VectorXd Bineq(2);
179
1
  Bineq(0) = -1.;
180
1
  Bineq(1) = -1.;
181
182
2
  Eigen::VectorXd x(2);
183
2
  Eigen::VectorXi activeSet(2);
184
  size_t activeSetSize;
185
186
2
  Eigen::VectorXd solution(2);
187
1
  solution(0) = 1.;
188
1
  solution(1) = 1.;
189
190
1
  double val = 1.;
191
192
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
193
194



1
  BOOST_CHECK_CLOSE(out, val, 1e-6);
195
196




3
  BOOST_CHECK(x.isApprox(solution));
197
1
}
198
199
// min ||x-x_0||^2, x_0 = (1 1)^T
200
//    s.t.
201
// x[1] = 5 - x[0]
202
// x[1] >= 3
203
204


















3
BOOST_AUTO_TEST_CASE(test_full) {
205
2
  Eigen::MatrixXd Q(2, 2);
206
1
  Q.setZero();
207
1
  Q(0, 0) = 1.0;
208
1
  Q(1, 1) = 1.0;
209
210
2
  Eigen::VectorXd C(2);
211
1
  C(0) = -1.;
212
1
  C(1) = -1.;
213
214
2
  Eigen::MatrixXd Aeq(2, 1);
215
1
  Aeq(0, 0) = 1.;
216
1
  Aeq(1, 0) = 1.;
217
218
2
  Eigen::VectorXd Beq(1);
219
1
  Beq(0) = -5.;
220
221
2
  Eigen::MatrixXd Aineq(2, 1);
222
1
  Aineq.setZero();
223
1
  Aineq(1, 0) = 1.;
224
225
2
  Eigen::VectorXd Bineq(1);
226
1
  Bineq(0) = -3.;
227
228
2
  Eigen::VectorXd x(2);
229
2
  Eigen::VectorXi activeSet(2);
230
  size_t activeSetSize;
231
232
2
  Eigen::VectorXd solution(2);
233
1
  solution(0) = 2.;
234
1
  solution(1) = 3.;
235
236
1
  double val = 1.5;
237
238
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
239
240



1
  BOOST_CHECK_CLOSE(out, val, 1e-6);
241
242




3
  BOOST_CHECK(x.isApprox(solution));
243
1
}
244
245
// min ||x||^2
246
//    s.t.
247
// x[0] =  1
248
// x[0] = -1
249
// DOES NOT WORK!
250
251


















3
BOOST_AUTO_TEST_CASE(test_unfeasible_equalities) {
252
2
  Eigen::MatrixXd Q(2, 2);
253
1
  Q.setZero();
254
1
  Q(0, 0) = 1.0;
255
1
  Q(1, 1) = 1.0;
256
257
2
  Eigen::VectorXd C(2);
258
1
  C.setZero();
259
260
2
  Eigen::MatrixXd Aeq(2, 2);
261
1
  Aeq.setZero();
262
1
  Aeq(0, 0) = 1.;
263
1
  Aeq(0, 1) = 1.;
264
265
2
  Eigen::VectorXd Beq(2);
266
1
  Beq(0) = -1.;
267
1
  Beq(1) = 1.;
268
269
2
  Eigen::MatrixXd Aineq(2, 0);
270
271
2
  Eigen::VectorXd Bineq(0);
272
273
2
  Eigen::VectorXd x(2);
274
2
  Eigen::VectorXi activeSet(2);
275
  size_t activeSetSize;
276
277
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
278
279
  // DOES NOT WORK!?
280



1
  BOOST_WARN(std::isinf(out));
281
1
}
282
283
// min ||x||^2
284
//    s.t.
285
// x[0] >=  1
286
// x[0] <= -1
287
288


















3
BOOST_AUTO_TEST_CASE(test_unfeasible_inequalities) {
289
2
  Eigen::MatrixXd Q(2, 2);
290
1
  Q.setZero();
291
1
  Q(0, 0) = 1.0;
292
1
  Q(1, 1) = 1.0;
293
294
2
  Eigen::VectorXd C(2);
295
1
  C.setZero();
296
297
2
  Eigen::MatrixXd Aeq(2, 0);
298
299
2
  Eigen::VectorXd Beq(0);
300
301
2
  Eigen::MatrixXd Aineq(2, 2);
302
1
  Aineq.setZero();
303
1
  Aineq(0, 0) = 1.;
304
1
  Aineq(0, 1) = -1.;
305
306
2
  Eigen::VectorXd Bineq(2);
307
1
  Bineq(0) = -1;
308
1
  Bineq(1) = -1;
309
310
2
  Eigen::VectorXd x(2);
311
2
  Eigen::VectorXi activeSet(2);
312
  size_t activeSetSize;
313
314
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
315
316



1
  BOOST_CHECK(std::isinf(out));
317
1
}
318
319
// min ||x-x_0||^2, x_0 = (1 1)^T
320
//    s.t.
321
// x[1] = 1 - x[0]
322
// x[0] <= 0
323
// x[1] <= 0
324
325


















3
BOOST_AUTO_TEST_CASE(test_unfeasible_constraints) {
326
2
  Eigen::MatrixXd Q(2, 2);
327
1
  Q.setZero();
328
1
  Q(0, 0) = 1.0;
329
1
  Q(1, 1) = 1.0;
330
331
2
  Eigen::VectorXd C(2);
332
1
  C(0) = -1.;
333
1
  C(1) = -1.;
334
335
2
  Eigen::MatrixXd Aeq(2, 1);
336
1
  Aeq(0, 0) = 1.;
337
1
  Aeq(1, 0) = 1.;
338
339
2
  Eigen::VectorXd Beq(1);
340
1
  Beq(0) = -1.;
341
342
2
  Eigen::MatrixXd Aineq(2, 2);
343
1
  Aineq.setZero();
344
1
  Aineq(0, 0) = -1.;
345
1
  Aineq(1, 1) = -1.;
346
347
2
  Eigen::VectorXd Bineq(2);
348
1
  Bineq.setZero();
349
350
2
  Eigen::VectorXd x(2);
351
2
  Eigen::VectorXi activeSet(3);
352
  size_t activeSetSize;
353
354
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
355
356



1
  BOOST_CHECK(std::isinf(out));
357
1
}
358
359
// min -||x||^2
360
// DOES NOT WORK!
361
362


















3
BOOST_AUTO_TEST_CASE(test_unbounded) {
363
2
  Eigen::MatrixXd Q(2, 2);
364
1
  Q.setZero();
365
1
  Q(0, 0) = -1.0;
366
1
  Q(1, 1) = -1.0;
367
368
2
  Eigen::VectorXd C(2);
369
1
  C.setZero();
370
371
2
  Eigen::MatrixXd Aeq(2, 0);
372
373
2
  Eigen::VectorXd Beq(0);
374
375
2
  Eigen::MatrixXd Aineq(2, 0);
376
377
2
  Eigen::VectorXd Bineq(0);
378
379
2
  Eigen::VectorXd x(2);
380
2
  Eigen::VectorXi activeSet(0);
381
  size_t activeSetSize;
382
383
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
384
385
  // DOES NOT WORK!?
386



1
  BOOST_WARN(std::isinf(out));
387
1
}
388
389
// min -||x||^2
390
//    s.t.
391
// 0<= x[0] <= 1
392
// 0<= x[1] <= 1
393
// DOES NOT WORK!
394
395


















3
BOOST_AUTO_TEST_CASE(test_nonconvex) {
396
2
  Eigen::MatrixXd Q(2, 2);
397
1
  Q.setZero();
398
1
  Q(0, 0) = -1.0;
399
1
  Q(1, 1) = -1.0;
400
401
2
  Eigen::VectorXd C(2);
402
1
  C.setZero();
403
404
2
  Eigen::MatrixXd Aeq(2, 0);
405
406
2
  Eigen::VectorXd Beq(0);
407
408
2
  Eigen::MatrixXd Aineq(2, 4);
409
1
  Aineq.setZero();
410
1
  Aineq(0, 0) = 1.;
411
1
  Aineq(0, 1) = -1.;
412
1
  Aineq(1, 2) = 1.;
413
1
  Aineq(1, 3) = -1.;
414
415
2
  Eigen::VectorXd Bineq(4);
416
1
  Bineq(0) = 0.;
417
1
  Bineq(1) = 1.;
418
1
  Bineq(2) = 0.;
419
1
  Bineq(3) = 1.;
420
421
2
  Eigen::VectorXd x(2);
422
2
  Eigen::VectorXi activeSet(4);
423
  size_t activeSetSize;
424
425
2
  Eigen::VectorXd solution(2);
426
1
  solution(0) = 1.;
427
1
  solution(1) = 1.;
428
429
1
  double val = -1.;
430
431
1
  double out = eiquadprog::solvers::solve_quadprog(Q, C, Aeq, Beq, Aineq, Bineq, x, activeSet, activeSetSize);
432
433
  // DOES NOT WORK!?
434



1
  BOOST_WARN_CLOSE(out, val, 1e-6);
435
436




3
  BOOST_WARN(x.isApprox(solution));
437
1
}
438
439

3
BOOST_AUTO_TEST_SUITE_END()