Skip to content

Commit d4d17b2

Browse files
authored
Merge pull request #923 from stan-dev/issue/922-sum-to-zero-transform
Updated sum-to-zero stan code
2 parents 6c8e490 + 58c3298 commit d4d17b2

1 file changed

Lines changed: 31 additions & 11 deletions

File tree

src/reference-manual/transforms.qmd

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -543,24 +543,24 @@ $$ and $$
543543
y_n = (S_n - x_{n + 1}) \frac{\sqrt{n (n + 1)}}{n}.
544544
$$
545545
546-
The mathematical expression above is equivalently expressed within Stan as:
546+
This transform is expressed in Stan code as:
547547
548548
``` stan
549-
vector manual_sum_to_zero_jacobian(vector y) {
550-
int N = num_elements(y);
551-
vector[N + 1] z = zeros_vector(N + 1);
549+
vector manual_sum_to_zero_jacobian(vector x) {
550+
int N = size(x) - 1;
551+
vector[N] y;
552+
y[N] = -x[N+1] * sqrt(1 + 1. / N);
552553
real sum_w = 0;
553-
for (n in 1:N) {
554-
int i = N - n + 1;
555-
real w = y[i] * inv_sqrt(i * (i + 1));
554+
for (n in 1:(N-1)) {
555+
int i = N - n;
556+
int i_p_1 = i + 1;
557+
real w = y[i_p_1] * inv_sqrt(i_p_1 * (i_p_1 + 1));
556558
sum_w += w;
557-
z[i] += sum_w;
558-
z[i + 1] -= w * i;
559+
y[i] = (sum_w - x[i_p_1]) * sqrt(i_p_1 * i) / i;
559560
}
560-
return z;
561+
return y;
561562
}
562563
```
563-
Note that there is no `target +=` increment because the Jacobian is zero.
564564
565565
### Sum-to-zero vector inverse transform {.unnumbered}
566566
@@ -585,6 +585,26 @@ subtracted from $x_{n + 1}$ the number of times it shows up in earlier terms.
585585
The inverse transform is a linear operation, leading to a constant Jacobian
586586
determinant which is therefore not included.
587587

588+
The sum-to-zero inverse transform is expressed within Stan as:
589+
590+
``` stan
591+
vector manual_sum_to_zero_inverse_jacobian(vector y) {
592+
int N = num_elements(y);
593+
vector[N + 1] x = zeros_vector(N + 1);
594+
real sum_w = 0;
595+
for (n in 1:N) {
596+
int i = N - n + 1;
597+
real w = y[i] * inv_sqrt(i * (i + 1));
598+
sum_w += w;
599+
x[i] += sum_w;
600+
x[i + 1] -= w * i;
601+
}
602+
return x;
603+
}
604+
```
605+
606+
Note that there is no `target +=` increment because the Jacobian is zero.
607+
588608
### Sum-to-zero matrix transform {.unnumbered}
589609

590610
The matrix case of the sum-to-zero transform generalizes the vector case to

0 commit comments

Comments
 (0)