tessl install tessl/pypi-ecos@2.0.1Python interface to ECOS, a numerical solver for convex second-order cone programs.
Complete API documentation for the ECOS Python interface.
def solve(c, G, h, dims, A=None, b=None, **kwargs):
"""
Solve a convex second-order cone program.
Solves optimization problems of the form:
minimize c'*x
subject to A*x = b (equality constraints)
G*x <=_K h (generalized cone inequality)
where <=_K denotes generalized inequality with respect to a cone K
that is a Cartesian product of positive orthant, second-order cones,
and optionally exponential cones.
Required Parameters
-------------------
c : numpy.ndarray
Objective coefficient vector.
- Shape: (n,) where n is the number of variables
- Type: float64 array
- Purpose: Defines linear objective c'*x to minimize
G : scipy.sparse.csc_matrix
Inequality constraint matrix.
- Shape: (m, n) where m is total cone dimension, n is number of variables
- Type: MUST be scipy.sparse.csc_matrix (Compressed Sparse Column)
- Purpose: Left-hand side of cone constraints G*x <=_K h
- Note: Will be converted to CSC with warning if not already
- Requirement: Number of columns must match length of c
h : numpy.ndarray
Inequality constraint right-hand side vector.
- Shape: (m,) where m matches number of rows in G
- Type: float64 array
- Purpose: Right-hand side of cone constraints G*x <=_K h
dims : dict
Cone dimension specification.
- Required keys:
- 'l' (int): Number of linear inequality constraints (positive orthant dimension)
- Must be non-negative integer
- Represents first dims['l'] rows of G*x <=_K h as linear inequalities
- 'q' (list of ints): List of second-order cone dimensions
- Must be a list (can be empty [])
- Each element specifies dimension of one second-order cone
- Cone Q_n = {(t,x) | t >= ||x||_2} has dimension n
- Optional keys:
- 'e' (int): Number of exponential cones
- Must be non-negative integer
- Each exponential cone has dimension 3
- Constraint: dims['l'] + sum(dims['q']) + 3*dims['e'] must equal m (rows of G)
Optional Parameters
-------------------
A : scipy.sparse.csc_matrix, optional
Equality constraint matrix.
- Shape: (p, n) where p is number of equality constraints, n is number of variables
- Type: MUST be scipy.sparse.csc_matrix
- Purpose: Left-hand side of equality constraints A*x = b
- Note: Must be provided together with b (both or neither)
- Requirement: Number of columns must match G columns (same n)
b : numpy.ndarray, optional
Equality constraint right-hand side vector.
- Shape: (p,) where p matches number of rows in A
- Type: float64 array
- Purpose: Right-hand side of equality constraints A*x = b
- Note: Must be provided together with A
Keyword Arguments (Solver Tolerances)
-------------------------------------
feastol : float, optional
Feasibility tolerance for primal and dual variables.
- Must be positive float
- Default: solver-specific (typically 1e-8)
- Controls when constraints are considered satisfied
abstol : float, optional
Absolute convergence tolerance.
- Must be positive float
- Default: solver-specific (typically 1e-8)
- Controls absolute accuracy of solution
reltol : float, optional
Relative convergence tolerance.
- Must be positive float
- Default: solver-specific (typically 1e-8)
- Controls relative accuracy of solution
feastol_inacc : float, optional
Inaccurate solution feasibility tolerance.
- Must be positive float
- Default: solver-specific (typically 1e-4)
- Used when accurate solution cannot be found
abstol_inacc : float, optional
Inaccurate solution absolute tolerance.
- Must be positive float
- Default: solver-specific (typically 5e-5)
reltol_inacc : float, optional
Inaccurate solution relative tolerance.
- Must be positive float
- Default: solver-specific (typically 5e-5)
Keyword Arguments (Solver Control)
----------------------------------
max_iters : int, optional
Maximum number of interior-point solver iterations.
- Must be non-negative integer
- Default: solver-specific (typically 100)
- Solver terminates after this many iterations even if not converged
nitref : int, optional
Number of iterative refinement steps after solving KKT system.
- Must be non-negative integer
- Default: solver-specific (typically 9)
- Improves numerical accuracy
verbose : bool, optional
Enable verbose solver output to stdout.
- Type: boolean (True/False)
- Default: False
- When True, prints iteration progress and convergence info
Keyword Arguments (Mixed-Integer)
---------------------------------
bool_vars_idx : list of ints, optional
Indices of boolean variables in x.
- Type: list of non-negative integers
- Default: [] (no boolean variables)
- Specifies which elements of solution x are restricted to {0, 1}
- Enables mixed-integer optimization via branch-and-bound
int_vars_idx : list of ints, optional
Indices of integer variables in x.
- Type: list of non-negative integers
- Default: [] (no integer variables)
- Specifies which elements of solution x are restricted to integers
- Enables mixed-integer optimization via branch-and-bound
mi_max_iters : int, optional
Maximum number of branch-and-bound iterations for mixed-integer problems.
- Must be non-negative integer
- Default: 1000
- Only relevant when bool_vars_idx or int_vars_idx is non-empty
mi_abs_eps : float, optional
Absolute tolerance between upper and lower bounds for mixed-integer problems.
- Must be positive float
- Default: 1e-6
- Branch-and-bound terminates when (upper_bound - lower_bound) < mi_abs_eps
mi_rel_eps : float, optional
Relative tolerance for mixed-integer problems.
- Must be positive float
- Default: 1e-3
- Branch-and-bound terminates when (U - L) / L < mi_rel_eps where U is upper bound, L is lower bound
mi_int_tol : float, optional
Integer tolerance for mixed-integer variables.
- Must be positive float
- Default: solver-specific (typically 1e-4)
- Variable is considered integer if within this distance of an integer value
mi_verbose : bool, optional
Enable verbose mixed-integer solver output.
- Type: boolean (True/False)
- Default: False
- When True, prints branch-and-bound progress
Returns
-------
dict
Solution dictionary with the following keys:
'x' : numpy.ndarray
Primal solution vector, shape (n,).
The optimal values of the optimization variables.
'y' : numpy.ndarray
Dual variables for equality constraints, shape (p,).
Empty array if no equality constraints (A and b not provided).
Lagrange multipliers for A*x = b constraints.
's' : numpy.ndarray
Slack variables for inequality constraints, shape (m,).
Satisfies s = h - G*x and s in K (s lies in the cone).
'z' : numpy.ndarray
Dual variables for cone constraints, shape (m,).
Lagrange multipliers for G*x <=_K h constraints.
Lies in the dual cone K*.
'info' : dict
Solver statistics and convergence information.
Contains implementation-specific fields such as:
- Iteration count
- Exit status/flag
- Timing information
- Optimality measures (primal/dual residuals, gap)
- Convergence indicators
Raises
------
TypeError
- If G is not a sparse matrix (when provided)
- If A is not a sparse matrix (when provided)
- If A is provided but b is not, or vice versa
- If both G and h are not provided together
- If number of columns in A and G don't match
- If keyword argument has incorrect type:
- verbose, mi_verbose must be bool
- max_iters, nitref, mi_max_iters must be int
- Tolerance parameters must be float
- bool_vars_idx, int_vars_idx must be list
- If dims['l'] is not an integer or is negative
- If dims['q'] is not a list
ValueError
- If keyword argument has invalid value:
- Tolerance parameters must be positive
- max_iters, nitref, mi_max_iters must be non-negative
- If dims['q'] contains non-positive integers
- If total cone dimensions don't match number of rows in G
- If dimensions of h don't match rows in G
- If dimensions of b don't match rows in A
- If lengths of c don't match columns in G
Notes
-----
- Matrices G and A are automatically converted to CSC format if not already,
with a warning printed to stderr
- If G and h are both None, an empty CSC matrix is created automatically
- For mixed-integer problems, the algorithm uses branch-and-bound on top of
the continuous conic solver
- Exponential cone support depends on the underlying C solver version
- The solver uses an interior-point method (primal-dual algorithm)
- Numerical stability can be improved by scaling the problem beforehand
"""__version__: strVersion string for the ECOS Python wrapper package.
Type: str
Example Values: "2.0.14", "2.0.13"
Usage:
import ecos
print(ecos.__version__) # "2.0.14"__solver_version__: strVersion string for the underlying ECOS C solver library.
Type: str
Example Values: "2.0.10", "2.0.9"
Usage:
import ecos
print(ecos.__solver_version__) # "2.0.10"Note: The Python wrapper version and C solver version may differ. The wrapper version typically tracks the Python packaging, while the solver version tracks the core C implementation.
The solve() function returns a dictionary with the following guaranteed keys:
solution: dict = {
'x': numpy.ndarray, # Primal solution
'y': numpy.ndarray, # Dual for equality constraints
's': numpy.ndarray, # Slack variables
'z': numpy.ndarray, # Dual for cone constraints
'info': dict # Solver information
}solution['x']numpy.ndarray(n,) where n is the number of optimization variablessolution['y']numpy.ndarray(p,) where p is the number of equality constraints, or (0,) if no equality constraintssolution['s']numpy.ndarray(m,) where m is the total cone dimensionsolution['z']numpy.ndarray(m,) where m is the total cone dimensionsolution['info']dictExample Access:
solution = ecos.solve(c, G, h, dims)
print("Exit flag:", solution['info'].get('exitFlag'))
print("Iterations:", solution['info'].get('iter'))
print("Solve time:", solution['info'].get('timing', {}).get('tsolve'))Sparse Matrix Requirement:
# ERROR: G must be sparse
G = np.array([[1.0, 2.0]]) # Dense array - will raise TypeError
solution = ecos.solve(c, G, h, dims) # TypeError: G must be a sparse matrix
# CORRECT:
G = sp.csc_matrix([[1.0, 2.0]]) # CSC sparse matrix
solution = ecos.solve(c, G, h, dims) # WorksA and b Must Be Provided Together:
# ERROR: Providing only A without b
A = sp.csc_matrix([[1.0]])
solution = ecos.solve(c, G, h, dims, A=A) # TypeError
# CORRECT: Provide both
A = sp.csc_matrix([[1.0]])
b = np.array([1.0])
solution = ecos.solve(c, G, h, dims, A=A, b=b) # WorksDimension Mismatch:
# ERROR: Columns of A and G must match
G = sp.csc_matrix([[1.0, 2.0]]) # 2 columns
A = sp.csc_matrix([[1.0, 2.0, 3.0]]) # 3 columns
solution = ecos.solve(c, G, h, dims, A=A, b=b) # TypeError
# CORRECT: Same number of variables
G = sp.csc_matrix([[1.0, 2.0]]) # 2 columns
A = sp.csc_matrix([[1.0, 2.0]]) # 2 columnsKeyword Argument Type Errors:
# ERROR: max_iters must be int
solution = ecos.solve(c, G, h, dims, max_iters=100.5) # TypeError: must be int
# ERROR: verbose must be bool
solution = ecos.solve(c, G, h, dims, verbose="true") # TypeError: must be bool
# CORRECT:
solution = ecos.solve(c, G, h, dims, max_iters=100, verbose=True)Tolerances Must Be Positive:
# ERROR: Negative tolerance
solution = ecos.solve(c, G, h, dims, feastol=-1e-8) # ValueError
# CORRECT:
solution = ecos.solve(c, G, h, dims, feastol=1e-8)Cone Dimensions Must Match:
# ERROR: dims don't match G dimensions
G = sp.csc_matrix(np.zeros((7, 3))) # 7 rows
dims = {'l': 5, 'q': []} # Only accounts for 5 rows
solution = ecos.solve(c, G, h, dims) # ValueError
# CORRECT: dims sum to 7
dims = {'l': 3, 'q': [4]} # 3 + 4 = 7
solution = ecos.solve(c, G, h, dims) # WorksInvalid Cone Dimensions:
# ERROR: Second-order cone must have dimension >= 1
dims = {'l': 0, 'q': [0]} # Invalid cone dimension
solution = ecos.solve(c, G, h, dims) # ValueError
# ERROR: dims['q'] must be a list
dims = {'l': 0, 'q': 3} # Should be [3], not 3
solution = ecos.solve(c, G, h, dims) # TypeError
# CORRECT:
dims = {'l': 0, 'q': [3]}ECOS will automatically convert non-CSC sparse matrices to CSC format with a warning:
G = sp.csr_matrix([[1.0, 2.0]]) # CSR format (not CSC)
solution = ecos.solve(c, G, h, dims) # Works but prints warning
# Warning: Converting G to CSC formatBest Practice: Always create matrices in CSC format to avoid conversion overhead:
G = sp.csc_matrix([[1.0, 2.0]]) # PreferredIf you have no inequality constraints, you can pass None for both G and h:
# Only equality constraints, no inequalities
A = sp.csc_matrix([[1.0, 1.0]])
b = np.array([5.0])
c = np.array([1.0, 1.0])
# G and h can be None
solution = ecos.solve(c, None, None, {'l': 0, 'q': []}, A=A, b=b)The solver will create an empty CSC matrix internally.
When bool_vars_idx or int_vars_idx is provided: