Coverage for lpsolvers / cvxopt_.py: 86%

29 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 

7"""Solver interface for CVXOPT.""" 

8 

9import logging 

10from typing import Optional 

11 

12import cvxopt 

13import cvxopt.solvers 

14import numpy as np 

15from cvxopt.solvers import lp 

16 

17cvxopt.solvers.options["show_progress"] = False # disable cvxopt output 

18 

19GLPK_IF_AVAILABLE: Optional[str] = None 

20 

21try: 

22 import cvxopt.glpk 

23 

24 GLPK_IF_AVAILABLE = "glpk" 

25 cvxopt.solvers.options["glpk"] = {"msg_lev": "GLP_MSG_OFF"} # cvxopt 1.1.8 

26 cvxopt.solvers.options["msg_lev"] = "GLP_MSG_OFF" # cvxopt 1.1.7 

27 cvxopt.solvers.options["LPX_K_MSGLEV"] = 0 # previous versions 

28except ImportError: 

29 # issue a warning as GLPK is the best LP solver in practice 

30 logging.warning("CVXOPT import: GLPK solver not found") 

31 

32 

33def cvxopt_matrix(M: np.ndarray) -> cvxopt.matrix: 

34 """ 

35 Convert matrix M to CVXOPT format. 

36 

37 Parameters 

38 ---------- 

39 M : 

40 Matrix to convert. 

41 

42 Returns 

43 ------- 

44 : 

45 Same matrix in CVXOPT format. 

46 """ 

47 if isinstance(M, cvxopt.matrix): 

48 return M 

49 return cvxopt.matrix(M) 

50 

51 

52def cvxopt_solve_lp( 

53 c: np.ndarray, 

54 G: np.ndarray, 

55 h: np.ndarray, 

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

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

58 solver: Optional[str] = GLPK_IF_AVAILABLE, 

59 **kwargs, 

60) -> np.ndarray: 

61 r"""Solve a linear program using CVXOPT. 

62 

63 The linear program is defined by: 

64 

65 .. math:: 

66 

67 \begin{split}\begin{array}{ll} 

68 \mbox{minimize} & 

69 c^T x \\ 

70 \mbox{subject to} 

71 & G x \leq h \\ 

72 & A x = b 

73 \end{array}\end{split} 

74 

75 It is solved using the LP solver from `CVXOPT <http://cvxopt.org/>`_. 

76 

77 Parameters 

78 ---------- 

79 c : 

80 Linear cost vector. 

81 G : 

82 Linear inequality constraint matrix. 

83 h : 

84 Linear inequality constraint vector. 

85 A : 

86 Linear equality constraint matrix. 

87 b : 

88 Linear equality constraint vector. 

89 solver : 

90 Solver to use, default is GLPK if available 

91 

92 Returns 

93 ------- 

94 : 

95 Optimal (primal) solution of the linear program, if it exists. 

96 

97 Raises 

98 ------ 

99 ValueError 

100 If the LP is not feasible. 

101 """ 

102 args = [cvxopt_matrix(c), cvxopt_matrix(G), cvxopt_matrix(h)] 

103 if A is not None and b is not None: 

104 args.extend([cvxopt_matrix(A), cvxopt_matrix(b)]) 

105 sol = lp(*args, solver=solver, **kwargs) 

106 if "optimal" not in sol["status"]: 

107 raise ValueError(f"LP optimum not found: {sol['status']}") 

108 n = c.shape[0] 

109 return np.array(sol["x"]).reshape((n,))