Skip to content

Commit a6e2342

Browse files
committed
jacobian of hstack
1 parent df861c3 commit a6e2342

14 files changed

Lines changed: 299 additions & 14 deletions

File tree

include/affine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ expr *new_linear(expr *u, const CSR_Matrix *A);
88

99
expr *new_add(expr *left, expr *right);
1010
expr *new_sum(expr *child, int axis);
11+
expr *new_hstack(expr **args, int n_args, int n_vars);
1112

1213
expr *new_constant(int d1, int d2, int n_vars, const double *values);
1314
expr *new_variable(int d1, int d2, int var_id, int n_vars);

include/expr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ typedef struct expr
3030
int refcount;
3131
struct expr *left;
3232
struct expr *right;
33+
struct expr **args; /* hstack can have multiple arguments */
34+
int n_args;
3335
double *dwork;
3436
int *iwork;
3537
struct int_double_pair *int_double_pairs; /* for sorting jacobian entries */

src/affine/add.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "affine.h"
22

3-
static void add_forward(expr *node, const double *u)
3+
static void forward(expr *node, const double *u)
44
{
55
/* children's forward passes */
66
node->left->forward(node->left, u);
@@ -52,7 +52,7 @@ expr *new_add(expr *left, expr *right)
5252
node->right = right;
5353
expr_retain(left);
5454
expr_retain(right);
55-
node->forward = add_forward;
55+
node->forward = forward;
5656
node->is_affine = is_affine;
5757
node->jacobian_init = jacobian_init;
5858
node->eval_jacobian = eval_jacobian;

src/affine/hstack.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include "affine.h"
2+
#include <assert.h>
3+
#include <string.h>
4+
5+
static void forward(expr *node, const double *u)
6+
{
7+
8+
/* children's forward passes */
9+
for (int i = 0; i < node->n_args; i++)
10+
{
11+
node->args[i]->forward(node->args[i], u);
12+
}
13+
14+
/* concatenate values horizontally */
15+
int offset = 0;
16+
for (int i = 0; i < node->n_args; i++)
17+
{
18+
expr *child = node->args[i];
19+
memcpy(node->value + offset, child->value, child->size * sizeof(double));
20+
offset += child->size;
21+
}
22+
}
23+
24+
static void jacobian_init(expr *node)
25+
{
26+
/* initialize children's jacobians */
27+
int nnz = 0;
28+
for (int i = 0; i < node->n_args; i++)
29+
{
30+
node->args[i]->jacobian_init(node->args[i]);
31+
nnz += node->args[i]->jacobian->nnz;
32+
}
33+
34+
node->jacobian = new_csr_matrix(node->size, node->n_vars, nnz);
35+
}
36+
37+
static void eval_jacobian(expr *node)
38+
{
39+
/* evaluate children's jacobians */
40+
int row_offset = 0;
41+
CSR_Matrix *A = node->jacobian;
42+
A->nnz = 0;
43+
44+
for (int i = 0; i < node->n_args; i++)
45+
{
46+
expr *child = node->args[i];
47+
child->eval_jacobian(child);
48+
CSR_Matrix *B = child->jacobian;
49+
50+
/* copy columns and values */
51+
memcpy(A->x + A->nnz, B->x, B->nnz * sizeof(double));
52+
memcpy(A->i + A->nnz, B->i, B->nnz * sizeof(int));
53+
54+
/* set row pointers */
55+
for (int r = 0; r < child->size; r++)
56+
{
57+
A->p[row_offset + r] = A->nnz + B->p[r];
58+
}
59+
60+
A->nnz += B->nnz;
61+
row_offset += child->size;
62+
}
63+
A->p[node->size] = A->nnz;
64+
}
65+
66+
static bool is_affine(expr *node)
67+
{
68+
for (int i = 0; i < node->n_args; i++)
69+
{
70+
if (!node->args[i]->is_affine(node->args[i]))
71+
{
72+
return false;
73+
}
74+
}
75+
return true;
76+
}
77+
78+
expr *new_hstack(expr **args, int n_args, int n_vars)
79+
{
80+
/* compute second dimension */
81+
int d2 = 0;
82+
for (int i = 0; i < n_args; i++)
83+
{
84+
d2 += args[i]->d2;
85+
}
86+
87+
expr *node = new_expr(args[0]->d1, d2, n_vars);
88+
if (!node) return NULL;
89+
node->args = args;
90+
node->n_args = n_args;
91+
92+
for (int i = 0; i < n_args; i++)
93+
{
94+
expr_retain(args[i]);
95+
}
96+
97+
node->forward = forward;
98+
node->is_affine = is_affine;
99+
node->jacobian_init = jacobian_init;
100+
node->eval_jacobian = eval_jacobian;
101+
102+
return node;
103+
}

src/elementwise_univariate/entr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static void forward(expr *node, const double *u)
1818
static void eval_local_jacobian(expr *node, double *vals)
1919
{
2020
expr *child = node->left;
21-
for (int j = 0; j < node->d1; j++)
21+
for (int j = 0; j < node->size; j++)
2222
{
2323
vals[j] = -log(child->value[j]) - 1.0;
2424
}

src/elementwise_univariate/exp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static void forward(expr *node, const double *u)
1616

1717
static void eval_local_jacobian(expr *node, double *vals)
1818
{
19-
memcpy(vals, node->value, node->d1 * sizeof(double));
19+
memcpy(vals, node->value, node->size * sizeof(double));
2020
}
2121

2222
expr *new_exp(expr *child)

src/elementwise_univariate/hyperbolic.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static void sinh_forward(expr *node, const double *u)
1414
static void sinh_eval_local_jacobian(expr *node, double *vals)
1515
{
1616
expr *child = node->left;
17-
for (int j = 0; j < node->d1; j++)
17+
for (int j = 0; j < node->size; j++)
1818
{
1919
vals[j] = cosh(child->value[j]);
2020
}
@@ -46,7 +46,7 @@ static void tanh_forward(expr *node, const double *u)
4646
static void tanh_eval_local_jacobian(expr *node, double *vals)
4747
{
4848
expr *child = node->left;
49-
for (int j = 0; j < node->d1; j++)
49+
for (int j = 0; j < node->size; j++)
5050
{
5151
double c = cosh(child->value[j]);
5252
vals[j] = 1.0 / (c * c);
@@ -79,7 +79,7 @@ static void asinh_forward(expr *node, const double *u)
7979
static void asinh_eval_local_jacobian(expr *node, double *vals)
8080
{
8181
expr *child = node->left;
82-
for (int j = 0; j < node->d1; j++)
82+
for (int j = 0; j < node->size; j++)
8383
{
8484
vals[j] = 1.0 / sqrt(1.0 + child->value[j] * child->value[j]);
8585
}
@@ -111,7 +111,7 @@ static void atanh_forward(expr *node, const double *u)
111111
static void atanh_eval_local_jacobian(expr *node, double *vals)
112112
{
113113
expr *child = node->left;
114-
for (int j = 0; j < node->d1; j++)
114+
for (int j = 0; j < node->size; j++)
115115
{
116116
vals[j] = 1.0 / (1.0 - child->value[j] * child->value[j]);
117117
}

src/elementwise_univariate/logistic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static void forward(expr *node, const double *u)
2626
static void eval_local_jacobian(expr *node, double *vals)
2727
{
2828
double *x = node->left->value;
29-
for (int j = 0; j < node->d1; j++)
29+
for (int j = 0; j < node->size; j++)
3030
{
3131
if (x[j] >= 0)
3232
{

src/elementwise_univariate/power.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static void forward(expr *node, const double *u)
1919
static void eval_local_jacobian(expr *node, double *vals)
2020
{
2121
double *x = node->left->value;
22-
for (int j = 0; j < node->d1; j++)
22+
for (int j = 0; j < node->size; j++)
2323
{
2424
vals[j] = node->p * pow(x[j], node->p - 1);
2525
}

src/elementwise_univariate/trig.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static void sin_forward(expr *node, const double *u)
1414
static void sin_eval_local_jacobian(expr *node, double *vals)
1515
{
1616
expr *child = node->left;
17-
for (int j = 0; j < node->d1; j++)
17+
for (int j = 0; j < node->size; j++)
1818
{
1919
vals[j] = cos(child->value[j]);
2020
}
@@ -46,7 +46,7 @@ static void cos_forward(expr *node, const double *u)
4646
static void cos_eval_local_jacobian(expr *node, double *vals)
4747
{
4848
expr *child = node->left;
49-
for (int j = 0; j < node->d1; j++)
49+
for (int j = 0; j < node->size; j++)
5050
{
5151
vals[j] = -sin(child->value[j]);
5252
}
@@ -78,7 +78,7 @@ static void tan_forward(expr *node, const double *u)
7878
static void tan_eval_local_jacobian(expr *node, double *vals)
7979
{
8080
expr *child = node->left;
81-
for (int j = 0; j < node->d1; j++)
81+
for (int j = 0; j < node->size; j++)
8282
{
8383
double c = cos(child->value[j]);
8484
vals[j] = 1.0 / (c * c);

0 commit comments

Comments
 (0)