Skip to content

Commit e5fb94e

Browse files
Transurgeonclaude
andcommitted
Add parameter support to DNLP diff engine
Enable cp.Parameter objects to be treated as updatable nodes in the C expression DAG instead of being baked in as constants. On re-solve with new parameter values, the cached DAG and sparsity structures are reused via problem._nlp_cache, analogous to DPP for conic programs. Requires SparseDiffPy PR #10 for make_parameter, problem_register_params, and problem_update_params bindings. Tests skip gracefully until installed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5f3d6c3 commit e5fb94e

6 files changed

Lines changed: 467 additions & 53 deletions

File tree

cvxpy/problems/problem.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def __init__(
176176
self._status: Optional[str] = None
177177
self._solution = None
178178
self._cache = Cache()
179+
self._nlp_cache = None
179180
self._solver_cache = {}
180181
# Information about the shape of the problem and its constituent parts
181182
self._size_metrics: Optional["SizeMetrics"] = None

cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,40 @@
2525
class C_problem:
2626
"""Wrapper around C problem struct for CVXPY problems."""
2727

28-
def __init__(self, cvxpy_problem: cp.Problem, verbose: bool = True):
28+
def __init__(self, cvxpy_problem: cp.Problem, verbose: bool = True,
29+
inverse_data=None):
30+
"""Create a C problem from a CVXPY problem.
31+
32+
Args:
33+
cvxpy_problem: CVXPY Problem object
34+
verbose: print solver output
35+
inverse_data: InverseData with param_id_map. When provided,
36+
cp.Parameter objects are converted to updatable C parameter
37+
nodes instead of being baked in as constants.
38+
"""
2939
var_dict, n_vars = build_variable_dict(cvxpy_problem.variables())
30-
c_obj = convert_expr(cvxpy_problem.objective.expr, var_dict, n_vars)
31-
c_constraints = [convert_expr(c.expr, var_dict, n_vars) for c in cvxpy_problem.constraints]
40+
41+
param_nodes = [] if inverse_data is not None else None
42+
c_obj = convert_expr(cvxpy_problem.objective.expr, var_dict, n_vars,
43+
inverse_data, param_nodes)
44+
c_constraints = [convert_expr(c.expr, var_dict, n_vars,
45+
inverse_data, param_nodes)
46+
for c in cvxpy_problem.constraints]
3247
self._capsule = _diffengine.make_problem(c_obj, c_constraints, verbose)
3348

49+
if param_nodes:
50+
_diffengine.problem_register_params(self._capsule, param_nodes)
51+
52+
def update_params(self, theta: np.ndarray) -> None:
53+
"""Update parameter values in the C DAG.
54+
55+
Sparsity structures (Jacobian/Hessian) remain valid after this call.
56+
57+
Args:
58+
theta: flat array of parameter values, ordered by InverseData offsets
59+
"""
60+
_diffengine.problem_update_params(self._capsule, theta)
61+
3462
def init_jacobian_coo(self):
3563
"""Fill sparsity for the constraint Jacobian in COO format.
3664

0 commit comments

Comments
 (0)