or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/ecos@2.0.x

docs

api-reference.mdexamples.mdindex.mdtroubleshooting.mdtypes-and-formats.md
tile.json

tessl/pypi-ecos

tessl install tessl/pypi-ecos@2.0.1

Python interface to ECOS, a numerical solver for convex second-order cone programs.

examples.mddocs/

ECOS Examples

Examples organized by complexity and use case. All examples assume these imports:

import ecos
import numpy as np
import scipy.sparse as sp

Basic Examples

Example 1: Simple Linear Programming

Minimize -x subject to x <= 4.

# Problem: minimize -x subject to x <= 4
c = np.array([-1.0])
G = sp.csc_matrix([[1.0]])
h = np.array([4.0])
dims = {'l': 1, 'q': []}

solution = ecos.solve(c, G, h, dims)
print("Optimal x:", solution['x'])  # [4.0]
print("Optimal value:", np.dot(c, solution['x']))  # -4.0

Explanation:

  • Objective: minimize -x (equivalent to maximize x)
  • Constraint: x <= 4
  • Solution: x = 4 is optimal (pushes against constraint)

Example 2: Multiple Linear Constraints

Minimize -x subject to x <= 4 and x >= 0.

# Problem: minimize -x subject to x <= 4 and x >= 0
c = np.array([-1.0])
G = sp.csc_matrix([[1.0], [-1.0]])
h = np.array([4.0, 0.0])
dims = {'l': 2, 'q': []}

solution = ecos.solve(c, G, h, dims, verbose=False)
print("Optimal x:", solution['x'])  # [4.0]
print("Optimal value:", np.dot(c, solution['x']))  # -4.0

Explanation:

  • First constraint: x <= 4
  • Second constraint: -x <= 0, which means x >= 0
  • Solution: x = 4 is optimal (upper bound is tight)

Example 3: Two-Variable Linear Program

Minimize -x1 - x2 subject to linear constraints.

# Problem:
#   minimize -x1 - x2
#   subject to:
#     2*x1 + x2 <= 4
#     x1 + 2*x2 <= 4
#     x1 >= 0
#     x2 >= 0

c = np.array([-1.0, -1.0])
G = sp.csc_matrix([
    [2.0, 1.0],   # 2*x1 + x2 <= 4
    [1.0, 2.0],   # x1 + 2*x2 <= 4
    [-1.0, 0.0],  # -x1 <= 0 (x1 >= 0)
    [0.0, -1.0]   # -x2 <= 0 (x2 >= 0)
])
h = np.array([4.0, 4.0, 0.0, 0.0])
dims = {'l': 4, 'q': []}

solution = ecos.solve(c, G, h, dims)
print("Optimal x:", solution['x'])  # Approximately [1.33, 1.33]
print("Optimal value:", np.dot(c, solution['x']))  # Approximately -2.67

Explanation:

  • Two-variable problem with four linear constraints
  • Solution is at the intersection of the two main constraints

Equality Constraints

Example 4: Linear Program with Equality

Minimize -x subject to x = 3.

# Problem: minimize -x subject to x = 3 and x <= 4
c = np.array([-1.0])
G = sp.csc_matrix([[1.0]])
h = np.array([4.0])
A = sp.csc_matrix([[1.0]])
b = np.array([3.0])
dims = {'l': 1, 'q': []}

solution = ecos.solve(c, G, h, dims, A, b)
print("Optimal x:", solution['x'])  # [3.0]
print("Dual y:", solution['y'])  # Lagrange multiplier for equality

Explanation:

  • Equality constraint fixes x = 3
  • Inequality x <= 4 is not tight (slack = 1)
  • Optimal value is -3

Example 5: Multiple Equality Constraints

Two variables with equality and inequality constraints.

# Problem:
#   minimize x1 + x2
#   subject to:
#     x1 + x2 = 5     (equality)
#     x1 - x2 = 1     (equality)
#     x1 >= 0, x2 >= 0

c = np.array([1.0, 1.0])
G = sp.csc_matrix([[-1.0, 0.0], [0.0, -1.0]])
h = np.array([0.0, 0.0])
A = sp.csc_matrix([[1.0, 1.0], [1.0, -1.0]])
b = np.array([5.0, 1.0])
dims = {'l': 2, 'q': []}

solution = ecos.solve(c, G, h, dims, A, b)
print("Optimal x:", solution['x'])  # [3.0, 2.0]
print("Verification: x1 + x2 =", solution['x'][0] + solution['x'][1])  # 5.0
print("Verification: x1 - x2 =", solution['x'][0] - solution['x'][1])  # 1.0

Explanation:

  • Two equality constraints uniquely determine the solution
  • x1 = 3, x2 = 2 satisfy both equalities
  • Both non-negativity constraints are satisfied

Second-Order Cone Programs

Example 6: Simple Second-Order Cone

Minimize -x0 subject to (x0, x1) in a second-order cone.

# Problem: minimize -x0 subject to x0 >= ||x1|| (L2 norm)
# This is equivalent to (x0, x1) in Q_2 where Q_2 is 2-dimensional SOC

c = np.array([-1.0, 0.0])
G = sp.csc_matrix([[1.0, 0.0], [0.0, 1.0]])
h = np.array([0.0, 0.0])
dims = {'l': 0, 'q': [2]}  # One second-order cone of dimension 2

solution = ecos.solve(c, G, h, dims)
print("Optimal solution:", solution['x'])
print("Verification: x0 >= |x1|:", solution['x'][0], ">=", abs(solution['x'][1]))

Explanation:

  • Second-order cone constraint: x0 >= ||x1||
  • Objective wants to maximize x0 (minimize -x0)
  • At optimum, x1 = 0 and x0 is as large as the constraint allows

Example 7: Norm Minimization

Minimize the L2 norm of a vector subject to linear constraints.

# Problem: minimize ||x|| subject to sum(x) >= 1, x >= 0
# Reformulate as:
#   minimize t
#   subject to (t, x) in SOC (t >= ||x||)
#              sum(x) >= 1
#              x >= 0

# Variables: [t, x1, x2, x3]
n = 4  # 1 for t, 3 for x components

c = np.array([1.0, 0.0, 0.0, 0.0])  # minimize t

# Cone constraint: (t, x1, x2, x3) in Q_4
G_soc = sp.csc_matrix([
    [1.0, 0.0, 0.0, 0.0],
    [0.0, 1.0, 0.0, 0.0],
    [0.0, 0.0, 1.0, 0.0],
    [0.0, 0.0, 0.0, 1.0]
])

# Linear constraints: -(x1 + x2 + x3) <= -1, -x1 <= 0, -x2 <= 0, -x3 <= 0
G_linear = sp.csc_matrix([
    [0.0, -1.0, -1.0, -1.0],  # sum(x) >= 1
    [0.0, -1.0, 0.0, 0.0],     # x1 >= 0
    [0.0, 0.0, -1.0, 0.0],     # x2 >= 0
    [0.0, 0.0, 0.0, -1.0]      # x3 >= 0
])

G = sp.vstack([G_soc, G_linear], format='csc')
h = np.array([0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0])

dims = {'l': 4, 'q': [4]}

solution = ecos.solve(c, G, h, dims)
t_opt = solution['x'][0]
x_opt = solution['x'][1:]
print("Optimal norm:", t_opt)
print("Optimal x:", x_opt)
print("Verification ||x||:", np.linalg.norm(x_opt))
print("Verification sum(x):", np.sum(x_opt))

Explanation:

  • Introduces auxiliary variable t to represent ||x||
  • SOC constraint enforces t >= ||x||
  • Objective minimizes t, which minimizes the norm

Example 8: Multiple Second-Order Cones

Problem with multiple SOC constraints.

# Problem with two separate SOC constraints
# Variables: [x1, x2, x3, x4, x5]
# Constraints:
#   x1 >= ||(x2, x3)||  (3-dimensional SOC)
#   x4 >= ||(x5,)||      (2-dimensional SOC)
#   Minimize x1 + x4

c = np.array([1.0, 0.0, 0.0, 1.0, 0.0])

# First SOC: (x1, x2, x3)
# Second SOC: (x4, x5)
G = sp.csc_matrix([
    # First SOC
    [1.0, 0.0, 0.0, 0.0, 0.0],
    [0.0, 1.0, 0.0, 0.0, 0.0],
    [0.0, 0.0, 1.0, 0.0, 0.0],
    # Second SOC
    [0.0, 0.0, 0.0, 1.0, 0.0],
    [0.0, 0.0, 0.0, 0.0, 1.0]
])

h = np.zeros(5)
dims = {'l': 0, 'q': [3, 2]}  # Two SOCs: dimension 3 and 2

solution = ecos.solve(c, G, h, dims)
print("Optimal solution:", solution['x'])
print("x1 >= ||(x2, x3)||:", solution['x'][0], ">=", np.linalg.norm(solution['x'][1:3]))
print("x4 >= ||x5||:", solution['x'][3], ">=", abs(solution['x'][4]))

Explanation:

  • Two independent second-order cone constraints
  • dims['q'] = [3, 2] specifies the two cone dimensions
  • Constraints are stacked in G matrix

Mixed-Integer Programming

Example 9: Boolean Variable

Linear program with one boolean variable.

# Problem:
#   minimize -x1 - x2
#   subject to:
#     2*x1 + x2 <= 4
#     3*x1 + 4*x2 <= 12
#     x1 >= 0, x2 >= 0
#     x2 in {0, 1}  (boolean)

c = np.array([-1.0, -1.0])
G = sp.csc_matrix([
    [2.0, 1.0],
    [3.0, 4.0],
    [-1.0, 0.0],
    [0.0, -1.0]
])
h = np.array([4.0, 12.0, 0.0, 0.0])
dims = {'l': 4, 'q': []}

# Specify that x2 (index 1) is boolean
solution = ecos.solve(
    c, G, h, dims,
    bool_vars_idx=[1],
    mi_max_iters=1000,
    verbose=False
)

print("Optimal solution:", solution['x'])
print("x2 is boolean:", solution['x'][1] in [0.0, 1.0])
print("Optimal value:", np.dot(c, solution['x']))

Explanation:

  • bool_vars_idx=[1] constrains x2 to be 0 or 1
  • Branch-and-bound explores both possibilities
  • Solution will have x2 exactly 0.0 or 1.0

Example 10: Multiple Integer Variables

Problem with both boolean and general integer variables.

# Problem:
#   minimize x1 + x2 + x3
#   subject to:
#     x1 + 2*x2 + 3*x3 >= 10
#     x1, x2, x3 >= 0
#     x1 in {0, 1}  (boolean)
#     x2 in Z+      (non-negative integer)
#     x3 continuous

c = np.array([1.0, 1.0, 1.0])
G = sp.csc_matrix([
    [-1.0, -2.0, -3.0],  # -(x1 + 2*x2 + 3*x3) <= -10
    [-1.0, 0.0, 0.0],    # x1 >= 0
    [0.0, -1.0, 0.0],    # x2 >= 0
    [0.0, 0.0, -1.0]     # x3 >= 0
])
h = np.array([-10.0, 0.0, 0.0, 0.0])
dims = {'l': 4, 'q': []}

solution = ecos.solve(
    c, G, h, dims,
    bool_vars_idx=[0],      # x1 is boolean
    int_vars_idx=[1],       # x2 is integer
    mi_max_iters=1000,
    mi_abs_eps=1e-6,
    mi_rel_eps=1e-3,
    verbose=False
)

print("Optimal solution:", solution['x'])
print("x1 (boolean):", solution['x'][0])
print("x2 (integer):", solution['x'][1])
print("x3 (continuous):", solution['x'][2])
print("Constraint satisfied:", np.dot([1, 2, 3], solution['x']), ">=", 10)

Explanation:

  • x1 is boolean (0 or 1)
  • x2 is a general integer (0, 1, 2, ...)
  • x3 is continuous
  • Branch-and-bound finds optimal integer assignment

Example 11: Knapsack-Style Problem

Integer optimization selecting items.

# Knapsack problem:
#   maximize value: 5*x1 + 7*x2 + 3*x3
#   subject to weight: 2*x1 + 3*x2 + 1*x3 <= 6
#   x1, x2, x3 in {0, 1}

c = np.array([-5.0, -7.0, -3.0])  # Negative for maximization
G = sp.csc_matrix([
    [2.0, 3.0, 1.0],   # Weight constraint
    [-1.0, 0.0, 0.0],  # x1 >= 0
    [0.0, -1.0, 0.0],  # x2 >= 0
    [0.0, 0.0, -1.0]   # x3 >= 0
])
h = np.array([6.0, 0.0, 0.0, 0.0])
dims = {'l': 4, 'q': []}

solution = ecos.solve(
    c, G, h, dims,
    bool_vars_idx=[0, 1, 2],  # All variables are boolean
    mi_max_iters=1000,
    verbose=False
)

print("Selected items:", solution['x'])
print("Total value:", -np.dot(c, solution['x']))
print("Total weight:", np.dot([2, 3, 1], solution['x']))

Explanation:

  • Classic 0-1 knapsack problem
  • Each variable represents whether to include an item
  • Constraint limits total weight

Advanced Options

Example 12: Custom Tolerances

Solving with tighter convergence criteria.

# Same problem as Example 2, but with custom tolerances
c = np.array([-1.0])
G = sp.csc_matrix([[1.0], [-1.0]])
h = np.array([4.0, 0.0])
dims = {'l': 2, 'q': []}

solution = ecos.solve(
    c, G, h, dims,
    feastol=1e-9,      # Tighter feasibility
    abstol=1e-9,       # Tighter absolute convergence
    reltol=1e-9,       # Tighter relative convergence
    max_iters=200,     # More iterations allowed
    verbose=True       # Show progress
)

print("Optimal x:", solution['x'])
print("Solver info:", solution['info'])

Explanation:

  • Default tolerances are typically 1e-8
  • Tighter tolerances give more accurate solutions
  • May require more iterations to converge

Example 13: Verbose Output and Diagnostics

Examining solver behavior.

c = np.array([-1.0])
G = sp.csc_matrix([[1.0], [-1.0]])
h = np.array([4.0, 0.0])
dims = {'l': 2, 'q': []}

solution = ecos.solve(c, G, h, dims, verbose=True)

# Examine solution dictionary
print("\n--- Solution Summary ---")
print("Primal solution x:", solution['x'])
print("Dual solution y:", solution['y'])
print("Slack variables s:", solution['s'])
print("Dual cone vars z:", solution['z'])

print("\n--- Solver Info ---")
info = solution['info']
for key, value in info.items():
    print(f"  {key}: {value}")

Explanation:

  • verbose=True prints iteration-by-iteration progress
  • solution['info'] contains detailed solver statistics
  • Useful for debugging convergence issues

Example 14: Iterative Refinement

Using more iterative refinement steps for accuracy.

c = np.array([-1.0])
G = sp.csc_matrix([[1.0], [-1.0]])
h = np.array([4.0, 0.0])
dims = {'l': 2, 'q': []}

solution = ecos.solve(
    c, G, h, dims,
    nitref=20,         # More iterative refinement (default ~9)
    verbose=False
)

print("Optimal x:", solution['x'])
print("Iterations used:", solution['info'])

Explanation:

  • nitref controls iterative refinement after KKT system solve
  • More refinement steps improve numerical accuracy
  • Useful for ill-conditioned problems

Integration Examples

Example 15: Using ECOS via CVXPY

ECOS is a default solver in CVXPY for convex problems.

import cvxpy as cp

# Define variables
x = cp.Variable(2)

# Define objective: minimize ||x||_2 + ||x||_1
objective = cp.Minimize(cp.norm(x, 2) + cp.norm(x, 1))

# Define constraints
constraints = [x >= 2]

# Create and solve problem
problem = cp.Problem(objective, constraints)
problem.solve(solver=cp.ECOS, verbose=True)

print("Optimal value:", problem.value)
print("Optimal x:", x.value)
print("Solver used:", problem.solver_stats.solver_name)

Explanation:

  • CVXPY automatically reformulates the problem for ECOS
  • Easier than manually setting up G, h, dims
  • Good for rapid prototyping

Example 16: Portfolio Optimization

Financial application using ECOS.

# Portfolio optimization: minimize risk, achieve target return
# Variables: x (portfolio weights)
# Objective: minimize risk = ||Σ^(1/2) * x||
# Constraints: expected_return' * x >= target, sum(x) = 1, x >= 0

import numpy as np
import scipy.sparse as sp

n_assets = 4
target_return = 0.08

# Expected returns
mu = np.array([0.05, 0.10, 0.08, 0.12])

# Covariance matrix (for simplicity, use diagonal)
Sigma = np.diag([0.01, 0.04, 0.02, 0.06])
Sigma_sqrt = np.sqrt(Sigma)  # Element-wise for diagonal

# Reformulate as SOCP:
# minimize t subject to (t, Σ^(1/2) * x) in SOC
# Variables: [t, x1, x2, x3, x4]

c = np.concatenate([[1.0], np.zeros(n_assets)])  # minimize t

# SOC constraint
G_soc = sp.csc_matrix(np.vstack([
    np.concatenate([[1.0], np.zeros(n_assets)]),
    np.concatenate([[0.0], Sigma_sqrt])
]))

# Linear constraints:
# sum(x) = 1 (equality)
# mu' * x >= target (inequality: -mu'*x <= -target)
# x >= 0
G_linear = sp.csc_matrix([
    np.concatenate([[0.0], -mu]),  # Expected return constraint
    np.concatenate([[0.0], [-1, 0, 0, 0]]),  # x1 >= 0
    np.concatenate([[0.0], [0, -1, 0, 0]]),  # x2 >= 0
    np.concatenate([[0.0], [0, 0, -1, 0]]),  # x3 >= 0
    np.concatenate([[0.0], [0, 0, 0, -1]])   # x4 >= 0
])

G = sp.vstack([G_soc, G_linear], format='csc')
h = np.array([0.0, 0.0, 0.0, 0.0, 0.0, -target_return, 0.0, 0.0, 0.0, 0.0])

A = sp.csc_matrix([np.concatenate([[0.0], np.ones(n_assets)])])
b = np.array([1.0])

dims = {'l': 5, 'q': [5]}

solution = ecos.solve(c, G, h, dims, A, b, verbose=False)

risk = solution['x'][0]
weights = solution['x'][1:]

print("Optimal portfolio risk:", risk)
print("Portfolio weights:", weights)
print("Expected return:", np.dot(mu, weights))
print("Weights sum to 1:", np.sum(weights))

Explanation:

  • Classic mean-variance portfolio optimization
  • Risk minimization formulated as SOCP
  • Demonstrates real-world application