Skip to content

Commit fe3a7ec

Browse files
authored
Merge pull request #328 from fabinsch/fix-infeas-detection
Fix infeasibility detection logic
2 parents f5ae9f1 + b7adeb8 commit fe3a7ec

File tree

5 files changed

+52
-6
lines changed

5 files changed

+52
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
### Fixed
10+
* Fix infeasibility detection and add a unit test ([#328](https://github.com/Simple-Robotics/proxsuite/pull/328))
11+
912
## [0.6.5] - 2024-05-31
1013

1114
### Added

include/proxsuite/proxqp/dense/utils.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (c) 2022 INRIA
2+
// Copyright (c) 2022-2024 INRIA
33
//
44
/**
55
* @file utils.hpp
@@ -289,7 +289,7 @@ global_primal_residual_infeasibility(
289289
//
290290
// the variables in entry are changed in place
291291

292-
bool res = infty_norm(dy.to_eigen()) != 0 && infty_norm(dz.to_eigen()) != 0;
292+
bool res = infty_norm(dy.to_eigen()) != 0 || infty_norm(dz.to_eigen()) != 0;
293293
if (!res) {
294294
return res;
295295
}

include/proxsuite/proxqp/sparse/utils.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (c) 2022-2023 INRIA
2+
// Copyright (c) 2022-2024 INRIA
33
//
44
/** \file */
55

@@ -488,7 +488,7 @@ global_primal_residual_infeasibility(VectorViewMut<T> ATdy,
488488
//
489489
// the variables in entry are changed in place
490490

491-
bool res = infty_norm(dy.to_eigen()) != 0 && infty_norm(dz.to_eigen()) != 0;
491+
bool res = infty_norm(dy.to_eigen()) != 0 || infty_norm(dz.to_eigen()) != 0;
492492
if (!res) {
493493
return res;
494494
}

test/src/dense_qp_eq.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (c) 2022 INRIA
2+
// Copyright (c) 2022 - 2024 INRIA
33
//
44
#include <iostream>
55
#include <doctest.hpp>
@@ -212,4 +212,45 @@ DOCTEST_TEST_CASE("linear problem with equality with equality constraints and "
212212
std::cout << "total number of iteration: " << qp.results.info.iter
213213
<< std::endl;
214214
}
215+
}
216+
217+
DOCTEST_TEST_CASE("infeasible qp")
218+
{
219+
// (x1- 9)^2 + (x2-6)^2
220+
// s.t.
221+
// x1 <= 10
222+
// x2 <= 10
223+
// x1 >= 20
224+
Eigen::Matrix<T, 2, 2> H;
225+
H << 1.0, 0.0, 0.0, 1.0;
226+
H = 2 * H;
227+
228+
Eigen::Matrix<T, 2, 1> g;
229+
g << -18.0, -12.0;
230+
231+
Eigen::Matrix<T, 3, 2> C;
232+
C << 1, 0, // x1 <= 10
233+
0, 1, // x2 <= 10
234+
-1, 0; // x1 >= 20
235+
236+
Eigen::Matrix<T, 3, 1> u;
237+
u << 10, 10, -20;
238+
239+
int n = H.rows();
240+
int n_in = C.rows();
241+
int n_eq = 0;
242+
243+
Eigen::Matrix<T, Eigen::Dynamic, 1> l =
244+
Eigen::Matrix<T, Eigen::Dynamic, 1>::Constant(
245+
n_in, -std::numeric_limits<double>::infinity());
246+
247+
proxsuite::proxqp::dense::QP<T> qp(n, n_eq, n_in);
248+
qp.init(H, g, nullopt, nullopt, C, l, u);
249+
qp.settings.eps_rel = 0.;
250+
qp.settings.eps_abs = 1e-9;
251+
252+
qp.solve();
253+
254+
DOCTEST_CHECK(qp.results.info.status ==
255+
proxsuite::proxqp::QPSolverOutput::PROXQP_PRIMAL_INFEASIBLE);
215256
}

test/src/dense_qp_with_eq_and_in.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality "
172172
<< "---testing sparse random strongly convex qp with degenerate "
173173
"inequality constraints and increasing dimension using the API---"
174174
<< std::endl;
175-
T sparsity_factor = 0.15;
175+
T sparsity_factor = 0.45;
176176
T eps_abs = T(1e-9);
177177
T strong_convexity_factor(1e-2);
178178
proxqp::utils::rand::set_seed(1);
@@ -197,6 +197,8 @@ DOCTEST_TEST_CASE("sparse random strongly convex qp with degenerate inequality "
197197
qp_random.l,
198198
qp_random.u);
199199
qp.solve();
200+
DOCTEST_CHECK(qp.results.info.status ==
201+
proxqp::QPSolverOutput::PROXQP_SOLVED);
200202
T pri_res = std::max(
201203
(qp_random.A * qp.results.x - qp_random.b).lpNorm<Eigen::Infinity>(),
202204
(helpers::positive_part(qp_random.C * qp.results.x - qp_random.u) +

0 commit comments

Comments
 (0)