Problem Data Updates

Clarabel allows for problem data to be updated and the solver re-run, provided that the overall problem shape (i.e. dimension and sparsity pattern) does not change.

Data updates can be applied to any matrix or vector term in the problem data, but not to the collection of cone constraints. Data updating is also not permitted when the solver settings specify either chordal_decomposition_enable = true or presolve_enable = true.

Data updates can be applied by specifying either:

  • A complete overwrite of the problem data component.
  • A partial overwrite, specifying both values and indices into the original data.

For matrix updates, it is also possible to overwrite the data by specifying a new sparse matrix structure. Note for updates of the quadratic term P in the objective, indexing is into the upper triangle of the data matrix, and updates must only specify the upper triangular part.

Python example

import clarabel
import numpy as np
from scipy import sparse

# Define problem data
P = sparse.csc_matrix([[6., 0.], [0., 4.]])
P = sparse.triu(P).tocsc()

q = np.array([-1., -4.])

A = sparse.csc_matrix(
    [[1., -2.],        # <-- LHS of equality constraint (lower bound)
     [1.,  0.],        # <-- LHS of inequality constraint (upper bound)
     [0.,  1.],        # <-- LHS of inequality constraint (upper bound)
     [-1.,  0.],       # <-- LHS of inequality constraint (lower bound)
     [0., -1.]])       # <-- LHS of inequality constraint (lower bound)

b = np.array([0., 1., 1., 1., 1.])

cones = [clarabel.ZeroConeT(1), clarabel.NonnegativeConeT(4)]
settings = clarabel.DefaultSettings()
settings.presolve_enable = False

solver = clarabel.DefaultSolver(P, q, A, b, cones, settings)

# complete vector data overwrite
qnew = np.array([0., 0.])

# partial vector data update
bv = np.array([0., 1.])
bi = np.array([1, 2])
bnew = (bi, bv)

# complete matrix data overwrite
Pnew = sparse.csc_matrix([[3., 0.], [0., 4.]]).tocsc()

# complete matrix data update (vector of nonzero values)
# NB: tuple of partial updates also works
Anew = A.data.copy()
Anew[1] = 2.

solver.update(q=qnew, P=Pnew, b=bnew, A=Anew)