1616 * limitations under the License.
1717 */
1818#include "affine.h"
19+ #include "utils/CSR_Matrix.h"
1920#include <assert.h>
2021#include <stdlib.h>
2122#include <string.h>
@@ -28,8 +29,8 @@ static void forward(expr *node, const double *u)
2829 /* child's forward pass */
2930 node -> left -> forward (node -> left , u );
3031
31- /* y = A * x */
32- csr_matvec (lin_node -> A_csr , x -> value , node -> value , x -> var_id );
32+ /* y = A * x (A is stored as node->jacobian) */
33+ csr_matvec (node -> jacobian , x -> value , node -> value , x -> var_id );
3334
3435 /* y += b (if offset exists) */
3536 if (lin_node -> b != NULL )
@@ -49,29 +50,17 @@ static bool is_affine(const expr *node)
4950static void free_type_data (expr * node )
5051{
5152 linear_op_expr * lin_node = (linear_op_expr * ) node ;
52- /* memory pointing to by A_csr will be freed when the jacobian is freed,
53- so if the jacobian is not null we must not free A_csr. */
54-
55- if (!node -> jacobian )
56- {
57- free_csr_matrix (lin_node -> A_csr );
58- }
59-
60- free_csc_matrix (lin_node -> A_csc );
61-
6253 if (lin_node -> b != NULL )
6354 {
6455 free (lin_node -> b );
6556 lin_node -> b = NULL ;
6657 }
67-
68- lin_node -> A_csr = NULL ;
69- lin_node -> A_csc = NULL ;
7058}
7159
7260static void jacobian_init_impl (expr * node )
7361{
74- node -> jacobian = ((linear_op_expr * ) node )-> A_csr ;
62+ /* jacobian is set at construction time — nothing to do */
63+ (void ) node ;
7564}
7665
7766static void eval_jacobian (expr * node )
@@ -80,21 +69,33 @@ static void eval_jacobian(expr *node)
8069 (void ) node ;
8170}
8271
72+ static void wsum_hess_init_impl (expr * node )
73+ {
74+ /* Linear operator Hessian is always zero */
75+ node -> wsum_hess = new_csr_matrix (node -> n_vars , node -> n_vars , 0 );
76+ }
77+
78+ static void eval_wsum_hess (expr * node , const double * w )
79+ {
80+ /* Linear operator Hessian is always zero - nothing to evaluate */
81+ (void ) node ;
82+ (void ) w ;
83+ }
84+
8385expr * new_linear (expr * u , const CSR_Matrix * A , const double * b )
8486{
8587 assert (u -> d2 == 1 );
8688 /* Allocate the type-specific struct */
8789 linear_op_expr * lin_node = (linear_op_expr * ) calloc (1 , sizeof (linear_op_expr ));
8890 expr * node = & lin_node -> base ;
8991 init_expr (node , A -> m , 1 , u -> n_vars , forward , jacobian_init_impl , eval_jacobian ,
90- is_affine , NULL , NULL , free_type_data );
92+ is_affine , wsum_hess_init_impl , eval_wsum_hess , free_type_data );
9193 node -> left = u ;
9294 expr_retain (u );
9395
94- /* Initialize type-specific fields */
95- lin_node -> A_csr = new_csr_matrix (A -> m , A -> n , A -> nnz );
96- copy_csr_matrix (A , lin_node -> A_csr );
97- lin_node -> A_csc = csr_to_csc (A );
96+ /* Store A directly as the jacobian (linear op jacobian is constant) */
97+ node -> jacobian = new_csr_matrix (A -> m , A -> n , A -> nnz );
98+ copy_csr_matrix (A , node -> jacobian );
9899
99100 /* Initialize offset (copy b if provided, otherwise NULL) */
100101 if (b != NULL )
0 commit comments