Skip to content

Commit 36b8ed9

Browse files
committed
some error checks and numerical diff to tests
1 parent 860dd5a commit 36b8ed9

10 files changed

Lines changed: 123 additions & 26 deletions

File tree

src/problem.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,13 @@ void problem_register_params(problem *prob, expr **param_nodes, int n_param_node
369369
prob->total_parameter_size = 0;
370370
for (int i = 0; i < n_param_nodes; i++)
371371
{
372+
373+
if (((parameter_expr *) param_nodes[i])->param_id == PARAM_FIXED)
374+
{
375+
fprintf(stderr, "can this ever happen? \n");
376+
exit(1);
377+
}
378+
372379
// TODO do we need to skip fixed params? maybe we adopt the convention
373380
// that we don't ever register fixed params?
374381
if (((parameter_expr *) param_nodes[i])->param_id == PARAM_FIXED) continue;
@@ -390,6 +397,13 @@ void problem_update_params(problem *prob, const double *theta)
390397
{
391398
expr *pnode = prob->param_nodes[i];
392399
parameter_expr *param = (parameter_expr *) pnode;
400+
401+
if (param->param_id == PARAM_FIXED)
402+
{
403+
fprintf(stderr, "can this ever happen? \n");
404+
exit(1);
405+
}
406+
393407
if (param->param_id == PARAM_FIXED) continue;
394408
int offset = param->param_id;
395409
memcpy(pnode->value, theta + offset, pnode->size * sizeof(double));

tests/all_tests.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ int main(void)
359359
mu_run_test(test_param_right_matmul_rectangular, tests_run);
360360
mu_run_test(test_param_shared_left_matmul_problem, tests_run);
361361
mu_run_test(test_param_fixed_skip_in_update, tests_run);
362+
mu_run_test(test_param_scalar_mult_problem_with_constant, tests_run);
362363

363364
printf("\n--- Parameter + Broadcast Tests ---\n");
364365
mu_run_test(test_constant_broadcast_vector_mult, tests_run);

tests/jacobian_tests/affine/test_left_matmul.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ const char *test_jacobian_left_matmul_exp_composite(void)
138138
expr *A_exp_Bx = new_left_matmul(NULL, exp_Bx, A);
139139

140140
mu_assert("check_jacobian failed",
141-
check_jacobian(A_exp_Bx, x_vals, NUMERICAL_DIFF_DEFAULT_H));
141+
check_jacobian_num(A_exp_Bx, x_vals, NUMERICAL_DIFF_DEFAULT_H));
142142

143143
free_csr_matrix(A);
144144
free_csr_matrix(B);

tests/jacobian_tests/composite/test_chain_rule_jacobian.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const char *test_jacobian_exp_sum(void)
1717
expr *exp_sum_x = new_exp(sum_x);
1818

1919
mu_assert("check_jacobian failed",
20-
check_jacobian(exp_sum_x, u_vals, NUMERICAL_DIFF_DEFAULT_H));
20+
check_jacobian_num(exp_sum_x, u_vals, NUMERICAL_DIFF_DEFAULT_H));
2121

2222
free_expr(exp_sum_x);
2323
return 0;
@@ -34,7 +34,7 @@ const char *test_jacobian_exp_sum_mult(void)
3434
expr *exp_sum_xy = new_exp(sum_xy);
3535

3636
mu_assert("check_jacobian failed",
37-
check_jacobian(exp_sum_xy, u_vals, NUMERICAL_DIFF_DEFAULT_H));
37+
check_jacobian_num(exp_sum_xy, u_vals, NUMERICAL_DIFF_DEFAULT_H));
3838

3939
free_expr(exp_sum_xy);
4040
return 0;
@@ -49,7 +49,7 @@ const char *test_jacobian_sin_cos(void)
4949
expr *sin_cos_x = new_sin(cos_x);
5050

5151
mu_assert("check_jacobian failed",
52-
check_jacobian(sin_cos_x, u_vals, NUMERICAL_DIFF_DEFAULT_H));
52+
check_jacobian_num(sin_cos_x, u_vals, NUMERICAL_DIFF_DEFAULT_H));
5353

5454
free_expr(sin_cos_x);
5555
return 0;
@@ -68,7 +68,7 @@ const char *test_jacobian_cos_sin_multiply(void)
6868
expr *multiply = new_elementwise_mult(sum, sin_y);
6969

7070
mu_assert("check_jacobian failed",
71-
check_jacobian(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
71+
check_jacobian_num(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
7272

7373
free_expr(multiply);
7474
return 0;
@@ -87,7 +87,7 @@ const char *test_jacobian_Ax_Bx_multiply(void)
8787
expr *multiply = new_elementwise_mult(Ax, Bx);
8888

8989
mu_assert("check_jacobian failed",
90-
check_jacobian(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
90+
check_jacobian_num(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
9191

9292
free_expr(multiply);
9393
free_csr_matrix(A);
@@ -107,7 +107,7 @@ const char *test_jacobian_AX_BX_multiply(void)
107107
expr *multiply = new_elementwise_mult(new_sin(AX), new_cos(BX));
108108

109109
mu_assert("check_jacobian failed",
110-
check_jacobian(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
110+
check_jacobian_num(multiply, u_vals, NUMERICAL_DIFF_DEFAULT_H));
111111

112112
free_expr(multiply);
113113
free_csr_matrix(A);
@@ -137,7 +137,7 @@ const char *test_jacobian_quad_form_Ax(void)
137137
expr *node = new_quad_form(sin_Ax, Q);
138138

139139
mu_assert("check_jacobian failed",
140-
check_jacobian(node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
140+
check_jacobian_num(node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
141141

142142
free_expr(node);
143143
free_csr_matrix(A);
@@ -164,7 +164,7 @@ const char *test_jacobian_quad_form_exp(void)
164164
expr *node = new_quad_form(exp_x, Q);
165165

166166
mu_assert("check_jacobian failed",
167-
check_jacobian(node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
167+
check_jacobian_num(node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
168168

169169
free_expr(node);
170170
free_csr_matrix(Q);
@@ -183,7 +183,7 @@ const char *test_jacobian_matmul_exp_exp(void)
183183
expr *Z = new_matmul(exp_X, exp_Y);
184184

185185
mu_assert("check_jacobian failed",
186-
check_jacobian(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
186+
check_jacobian_num(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
187187

188188
free_expr(Z);
189189
return 0;
@@ -201,7 +201,7 @@ const char *test_jacobian_matmul_sin_cos(void)
201201
expr *Z = new_matmul(sin_X, cos_Y);
202202

203203
mu_assert("check_jacobian failed",
204-
check_jacobian(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
204+
check_jacobian_num(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
205205

206206
free_expr(Z);
207207
return 0;
@@ -222,7 +222,7 @@ const char *test_jacobian_matmul_Ax_By(void)
222222
expr *Z = new_matmul(AX, BY); /* 3x2 */
223223

224224
mu_assert("check_jacobian failed",
225-
check_jacobian(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
225+
check_jacobian_num(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
226226

227227
free_expr(Z);
228228
free_csr_matrix(A);
@@ -246,7 +246,7 @@ const char *test_jacobian_matmul_sin_Ax_cos_Bx(void)
246246
expr *Z = new_matmul(sin_AX, cos_BX); /* 2x2 */
247247

248248
mu_assert("check_jacobian failed",
249-
check_jacobian(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
249+
check_jacobian_num(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
250250

251251
free_expr(Z);
252252
free_csr_matrix(A);
@@ -263,7 +263,7 @@ const char *test_jacobian_matmul_X_X(void)
263263
expr *Z = new_matmul(X, X); /* 2x2 */
264264

265265
mu_assert("check_jacobian failed",
266-
check_jacobian(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
266+
check_jacobian_num(Z, u_vals, NUMERICAL_DIFF_DEFAULT_H));
267267

268268
free_expr(Z);
269269
return 0;

tests/jacobian_tests/composite/test_composite_exp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const char *test_jacobian_composite_exp_add(void)
7171
expr *sum = new_add(exp_Ax, exp_By);
7272

7373
mu_assert("check_jacobian failed",
74-
check_jacobian(sum, u_vals, NUMERICAL_DIFF_DEFAULT_H));
74+
check_jacobian_num(sum, u_vals, NUMERICAL_DIFF_DEFAULT_H));
7575

7676
free_expr(sum);
7777
free_csr_matrix(A);

tests/numerical_diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ double *numerical_jacobian(expr *node, const double *u, double h)
6161
return J;
6262
}
6363

64-
int check_jacobian(expr *node, const double *u, double h)
64+
int check_jacobian_num(expr *node, const double *u, double h)
6565
{
6666
int m = node->size;
6767
int n = node->n_vars;

tests/numerical_diff.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ double *numerical_jacobian(expr *node, const double *u, double h);
1313
/* Evaluate analytical Jacobian, compute numerical Jacobian,
1414
* and compare. Returns 1 on match, 0 on mismatch.
1515
* Prints diagnostic on first failing entry. */
16-
int check_jacobian(expr *node, const double *u, double h);
16+
int check_jacobian_num(expr *node, const double *u, double h);
1717

1818
/* Compute dense numerical weighted-sum Hessian via central
1919
* differences on the gradient g(u) = J(u)^T w.

tests/numerical_diff/test_numerical_diff.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const char *test_check_jacobian_composite_exp(void)
2222
expr *exp_node = new_exp(Au);
2323

2424
mu_assert("check_jacobian failed",
25-
check_jacobian(exp_node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
25+
check_jacobian_num(exp_node, u_vals, NUMERICAL_DIFF_DEFAULT_H));
2626

2727
free_expr(exp_node);
2828
free_csr_matrix(A);

tests/problem/test_param_broadcast.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "atoms/affine.h"
99
#include "expr.h"
1010
#include "minunit.h"
11+
#include "numerical_diff.h"
1112
#include "problem.h"
1213
#include "subexpr.h"
1314
#include "test_helpers.h"
@@ -37,6 +38,9 @@ const char *test_constant_broadcast_vector_mult(void)
3738
mu_assert("vals fail", cmp_double_array(prob->constraint_values, constrs, 6));
3839
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, jac_x, 6));
3940

41+
mu_assert("check_jacobian failed",
42+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
43+
4044
free_problem(prob);
4145
return 0;
4246
}
@@ -67,6 +71,9 @@ const char *test_constant_promote_vector_mult(void)
6771
mu_assert("vals fail", cmp_double_array(prob->constraint_values, constrs, 6));
6872
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, jac_x, 6));
6973

74+
mu_assert("check_jacobian failed",
75+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
76+
7077
free_problem(prob);
7178
return 0;
7279
}
@@ -99,16 +106,23 @@ const char *test_param_broadcast_vector_mult(void)
99106
mu_assert("vals fail", cmp_double_array(prob->constraint_values, constrs, 6));
100107
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, jac_x, 6));
101108

109+
mu_assert("check_jacobian failed",
110+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
111+
102112
/* second iteration after updating parameter */
103113
double theta[3] = {5.0, 4.0, 3.0};
104114
problem_update_params(prob, theta);
105115
problem_constraint_forward(prob, x_vals);
106116
problem_jacobian(prob);
107117
double updated_constrs[6] = {5.0, 10.0, 12.0, 16.0, 15.0, 18.0};
108118
double updated_jac_x[6] = {5.0, 5.0, 4.0, 4.0, 3.0, 3.0};
109-
mu_assert("vals fail", cmp_double_array(prob->constraint_values, updated_constrs, 6));
119+
mu_assert("vals fail",
120+
cmp_double_array(prob->constraint_values, updated_constrs, 6));
110121
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, updated_jac_x, 6));
111122

123+
mu_assert("check_jacobian failed",
124+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
125+
112126
free_problem(prob);
113127
return 0;
114128
}
@@ -141,16 +155,23 @@ const char *test_param_promote_vector_mult(void)
141155
mu_assert("vals fail", cmp_double_array(prob->constraint_values, constrs, 6));
142156
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, jac_x, 6));
143157

158+
mu_assert("check_jacobian failed",
159+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
160+
144161
/* second iteration after updating parameter */
145162
double theta = 5.0;
146163
problem_update_params(prob, &theta);
147164
problem_constraint_forward(prob, x_vals);
148165
problem_jacobian(prob);
149166
double updated_constrs[6] = {5.0, 10.0, 15.0, 20.0, 25.0, 30.0};
150167
double updated_jac_x[6] = {5.0, 5.0, 5.0, 5.0, 5.0, 5.0};
151-
mu_assert("vals fail", cmp_double_array(prob->constraint_values, updated_constrs, 6));
168+
mu_assert("vals fail",
169+
cmp_double_array(prob->constraint_values, updated_constrs, 6));
152170
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, updated_jac_x, 6));
153171

172+
mu_assert("check_jacobian failed",
173+
check_jacobian_num(constraint, x_vals, NUMERICAL_DIFF_DEFAULT_H));
174+
154175
free_problem(prob);
155176
return 0;
156177
}

tests/problem/test_param_prob.h

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,53 @@ const char *test_param_scalar_mult_problem(void)
5858
return 0;
5959
}
6060

61+
const char *test_param_scalar_mult_problem_with_constant(void)
62+
{
63+
int n = 2;
64+
65+
/* minimize a * (sum(log(x)) + c), with a parameter, c = 4 constant */
66+
expr *x = new_variable(2, 1, 0, n);
67+
expr *log_x = new_log(x);
68+
double theta[1] = {3.0};
69+
double c_val = 4.0;
70+
expr *a_param = new_parameter(1, 1, 0, n, theta);
71+
expr *c = new_parameter(1, 1, PARAM_FIXED, n, &c_val);
72+
expr *scaled = new_scalar_mult(a_param, new_add(new_sum(log_x, -1), c));
73+
expr *objective = new_sum(scaled, -1);
74+
problem *prob = new_problem(objective, NULL, 0, false);
75+
76+
/* register parameters and fill sparsity patterns */
77+
expr *param_nodes[1] = {a_param};
78+
problem_register_params(prob, param_nodes, 1);
79+
problem_init_derivatives(prob);
80+
81+
/* point for evaluating */
82+
double x_vals[2] = {1.0, 2.0};
83+
84+
/* test 1: a=3 */
85+
double obj_val = problem_objective_forward(prob, x_vals);
86+
problem_gradient(prob);
87+
double expected_obj = 3.0 * (log(2.0) + 4.0);
88+
mu_assert("vals fail", fabs(obj_val - expected_obj) < 1e-10);
89+
double grad[2] = {3.0, 1.5};
90+
mu_assert("vals fail", cmp_double_array(prob->gradient_values, grad, 2));
91+
92+
/* test 2: a=5 */
93+
theta[0] = 5.0;
94+
problem_update_params(prob, theta);
95+
obj_val = problem_objective_forward(prob, x_vals);
96+
problem_gradient(prob);
97+
expected_obj = 5.0 * (log(2.0) + 4.0);
98+
mu_assert("vals fail", fabs(obj_val - expected_obj) < 1e-10);
99+
grad[0] = 5.0;
100+
grad[1] = 2.5;
101+
mu_assert("vals fail", cmp_double_array(prob->gradient_values, grad, 2));
102+
103+
free_problem(prob);
104+
105+
return 0;
106+
}
107+
61108
const char *test_param_vector_mult_problem(void)
62109
{
63110
int n = 2;
@@ -148,7 +195,10 @@ const char *test_param_left_matmul_problem(void)
148195
mu_assert("cols fail", cmp_int_array(prob->jacobian->i, Ai, 4));
149196

150197
/* test 2: A = [[1,2],[3,4]] (column-major [1,3,2,4]) */
151-
theta[0] = 1.0; theta[1] = 3.0; theta[2] = 2.0; theta[3] = 4.0;
198+
theta[0] = 1.0;
199+
theta[1] = 3.0;
200+
theta[2] = 2.0;
201+
theta[3] = 4.0;
152202
problem_update_params(prob, theta);
153203
problem_constraint_forward(prob, x_vals);
154204
problem_jacobian(prob);
@@ -321,8 +371,12 @@ const char *test_param_left_matmul_rectangular(void)
321371
mu_assert("cols fail", cmp_int_array(prob->jacobian->i, Ai, 6));
322372

323373
/* test 2: A = [[7,8],[9,10],[11,12]] (column-major [7,9,11,8,10,12]) */
324-
theta[0] = 7.0; theta[1] = 9.0; theta[2] = 11.0;
325-
theta[3] = 8.0; theta[4] = 10.0; theta[5] = 12.0;
374+
theta[0] = 7.0;
375+
theta[1] = 9.0;
376+
theta[2] = 11.0;
377+
theta[3] = 8.0;
378+
theta[4] = 10.0;
379+
theta[5] = 12.0;
326380
problem_update_params(prob, theta);
327381
problem_constraint_forward(prob, x_vals);
328382
problem_jacobian(prob);
@@ -383,8 +437,12 @@ const char *test_param_right_matmul_rectangular(void)
383437
mu_assert("vals fail", cmp_double_array(prob->jacobian->x, jac_x, 6));
384438

385439
/* test 2: A = [[7,8,9],[10,11,12]] (column-major [7,10,8,11,9,12]) */
386-
theta[0] = 7.0; theta[1] = 10.0; theta[2] = 8.0;
387-
theta[3] = 11.0; theta[4] = 9.0; theta[5] = 12.0;
440+
theta[0] = 7.0;
441+
theta[1] = 10.0;
442+
theta[2] = 8.0;
443+
theta[3] = 11.0;
444+
theta[4] = 9.0;
445+
theta[5] = 12.0;
388446
problem_update_params(prob, theta);
389447
problem_constraint_forward(prob, x_vals);
390448
problem_jacobian(prob);
@@ -447,7 +505,10 @@ const char *test_param_shared_left_matmul_problem(void)
447505
mu_assert("cols fail", cmp_int_array(prob->jacobian->i, Ai, 8));
448506

449507
/* test 2: A = [[1,2],[3,4]] (column-major [1,3,2,4]) */
450-
theta[0] = 1.0; theta[1] = 3.0; theta[2] = 2.0; theta[3] = 4.0;
508+
theta[0] = 1.0;
509+
theta[1] = 3.0;
510+
theta[2] = 2.0;
511+
theta[3] = 4.0;
451512
problem_update_params(prob, theta);
452513
problem_constraint_forward(prob, x_vals);
453514
problem_jacobian(prob);

0 commit comments

Comments
 (0)