Coverage for lpsolvers / proxqp_.py: 78%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-20 15:19 +0000

1#!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3# 

4# SPDX-License-Identifier: LGPL-3.0-or-later 

5# Copyright (C) 2016-2022 Stéphane Caron 

6# Copyright (C) 2023 Inria 

7 

8"""Solver interface for `ProxQP`_. 

9 

10.. _ProxQP: https://github.com/Simple-Robotics/proxsuite#proxqp 

11 

12ProxQP is the QP solver from ProxSuite, a collection of open-source solvers 

13rooted in revisited primal-dual proximal algorithms. If you use ProxQP in some 

14academic work, consider citing the corresponding paper [Bambade2022]_. 

15""" 

16 

17from typing import Optional 

18 

19import numpy as np 

20from proxsuite import proxqp 

21 

22 

23def __select_backend(backend: Optional[str], use_csc: bool): 

24 """Select backend function for ProxQP. 

25 

26 Parameters 

27 ---------- 

28 backend : 

29 ProxQP backend to use in ``[None, "dense", "sparse"]``. If ``None`` 

30 (default), the backend is selected based on the type of ``P``. 

31 use_csc : 

32 If ``True``, use sparse matrices if the backend is not specified. 

33 

34 Returns 

35 ------- 

36 : 

37 Backend solve function. 

38 

39 Raises 

40 ------ 

41 ParamError 

42 If the required backend is not a valid ProxQP backend. 

43 """ 

44 if backend is None: 

45 return proxqp.sparse if use_csc else proxqp.dense 

46 if backend == "dense": 

47 return proxqp.dense 

48 if backend == "sparse": 

49 return proxqp.sparse 

50 raise ValueError(f'Unknown ProxQP backend "{backend}') 

51 

52 

53def proxqp_solve_lp( 

54 c: np.ndarray, 

55 G: np.ndarray, 

56 h: np.ndarray, 

57 A: Optional[np.ndarray] = None, 

58 b: Optional[np.ndarray] = None, 

59 verbose: bool = False, 

60 backend: Optional[str] = None, 

61 **kwargs, 

62) -> np.ndarray: 

63 """Solve a quadratic program using ProxQP. 

64 

65 Parameters 

66 ---------- 

67 c : 

68 Linear cost vector. 

69 G : 

70 Linear inequality constraint matrix. 

71 h : 

72 Linear inequality constraint vector. 

73 A : 

74 Linear equality constraint matrix. 

75 b : 

76 Linear equality constraint vector. 

77 backend : 

78 ProxQP backend to use in ``[None, "dense", "sparse"]``. If ``None`` 

79 (default), the backend is selected based on the type of ``P``. 

80 verbose : 

81 Set to `True` to print out extra information. 

82 

83 Returns 

84 ------- 

85 : 

86 Solution to the QP returned by the solver. 

87 

88 Notes 

89 ----- 

90 All other keyword arguments are forwarded as solver settings to ProxQP. For 

91 instance, you can call ``proxqp_solve_qp(P, q, G, h, eps_abs=1e-6)``. Check 

92 out the `solver documentation 

93 <https://simple-robotics.github.io/proxsuite/>`__ for details. 

94 """ 

95 use_csc: bool = (G is not None and not isinstance(G, np.ndarray)) or ( 

96 A is not None and not isinstance(A, np.ndarray) 

97 ) 

98 proxqp_backend = __select_backend(backend, use_csc) 

99 problem = proxqp_backend.QP( 

100 n=c.shape[0], 

101 n_eq=b.shape[0] if b is not None else 0, 

102 n_in=h.shape[0] if h is not None else 0, 

103 hessian_type=proxqp_backend.HessianType.Zero, 

104 ) 

105 for key, value in kwargs.items(): 

106 setattr(problem.settings, key, value) 

107 problem.settings.verbose = verbose 

108 problem.init(None, c, None, None, G, None, h) 

109 problem.solve() 

110 if problem.results.info.status != proxqp.PROXQP_SOLVED: 

111 raise ValueError("Linear program is not feasible") 

112 return problem.results.x