@@ -41,6 +41,7 @@ typedef struct problem
4141} problem;
4242
4343problem * new_problem(expr * objective, expr ** constraints, int n_constraints);
44+ void problem_allocate(problem * prob, const double * u);
4445void free_problem(problem * prob);
4546double problem_forward(problem * prob, const double * u);
4647double * problem_gradient(problem * prob, const double * u);
@@ -58,7 +59,38 @@ Key functions:
5859### ` new_problem `
5960- Retain (increment refcount) on objective and all constraints
6061- Compute ` total_constraint_size = sum(constraints[i]->size) `
61- - Pre-allocate ` constraint_values ` and ` gradient_values ` arrays
62+ - Does NOT allocate storage arrays (use ` problem_allocate ` separately)
63+
64+ ### ` problem_allocate `
65+ Separate function to allocate memory for constraint values and jacobian:
66+
67+ ``` c
68+ void problem_allocate (problem * prob, const double * u)
69+ {
70+ /* 1. Allocate constraint values array * /
71+ prob->constraint_values = malloc(prob->total_constraint_size * sizeof(double));
72+
73+ /* 2. Allocate jacobian:
74+ * - First, initialize all constraint jacobians
75+ * - Count total nnz across all constraints
76+ * - Allocate CSR matrix with this nnz (may be slight overestimate)
77+ */
78+ int total_nnz = 0;
79+ for (int i = 0; i < prob->n_constraints; i++)
80+ {
81+ expr *c = prob->constraints[i];
82+ c->forward(c, u);
83+ c->jacobian_init(c);
84+ total_nnz += c->jacobian->nnz;
85+ }
86+
87+ /* Allocate stacked jacobian with total_constraint_size rows */
88+ prob->stacked_jac = alloc_csr(prob->total_constraint_size, prob->n_vars, total_nnz);
89+
90+ /* Note: The actual nnz may be smaller after evaluation due to
91+ * cancellations. Update stacked_jac->nnz after problem_jacobian(). */
92+ }
93+ ```
6294
6395### `free_problem`
6496- Call `free_expr` on objective and all constraints (decrements refcount)
@@ -201,5 +233,9 @@ class Problem:
201233## Key Design Notes
202234
203235- ** Memory** : Uses expr refcounting - new_problem retains, free_problem releases
204- - ** Efficiency** : Pre-allocates arrays, lazy-allocates stacked jacobian
236+ - ** Two-phase init** : ` new_problem ` creates struct, ` problem_allocate ` allocates arrays
237+ - Constraint values array: size = ` total_constraint_size `
238+ - Jacobian: initialize all constraint jacobians first, count total nnz, allocate CSR
239+ - The allocated nnz may be a slight overestimate; update ` stacked_jac->nnz ` after evaluation
240+ - ** Hessian** : Deferred - not allocated in this design (to be added later)
205241- ** API** : Returns internal pointers (caller should NOT free)
0 commit comments