Skip to content

User-defined constrained parameterizations#967

Open
bob-carpenter wants to merge 20 commits into
masterfrom
fun-distributions
Open

User-defined constrained parameterizations#967
bob-carpenter wants to merge 20 commits into
masterfrom
fun-distributions

Conversation

@bob-carpenter

Copy link
Copy Markdown
Member

This is a whole new chapter on user-defined constrained parameters with some challenging examples. I've tested that all the code actually works.

Submission Checklist

  • Builds locally
  • [n/a] New functions marked with <<{ since VERSION }>>
  • Declare copyright holder and open-source license: see below

Summary

Copyright and Licensing

Please list the copyright holder for the work you are submitting (this will be you or your assignee, such as a university or company):

Simons Foundation

By submitting this pull request, the copyright holder is agreeing to license the submitted work under the following licenses:

@bob-carpenter bob-carpenter changed the title Fun distributions User-defined constrained parameterizations Jul 17, 2026
@bob-carpenter bob-carpenter changed the title User-defined constrained parameterizations [WIP] User-defined constrained parameterizations Jul 17, 2026
@bob-carpenter

Copy link
Copy Markdown
Member Author

I renamed and tagged "WIP" because I want to go over and add a little more text background and also citations to the original threads that introduced these ideas.

@bob-carpenter bob-carpenter changed the title [WIP] User-defined constrained parameterizations User-defined constrained parameterizations Jul 21, 2026
@bob-carpenter

Copy link
Copy Markdown
Member Author

@WardBrian. This is now code complete, spell checked, and read over by me. Sorry, but I sort of got carried away, and as a result, it's a lot.

@WardBrian WardBrian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun read. A bunch of comments below

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to reassess https://mc-stan.org/docs/stan-users-guide/reparameterization.html#changes-of-variables and see if that should just be blended into this new chapter (or at least cross-referenced)

real log_sigma;
}
transformed parameters {
real<lower=0> sigma = exp(log_sigma);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth explicitly (re)-stating that the lower= syntax only performs checks in blocks other than parameters

Comment on lines +278 to +281
if (cols(x) != N + binom(N, 2)) {
reject("cols(x) = ", cols(x),
"; but N + binom(N, 2) = ", N + binom(N, 2));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

binom is not a function; it's choose (which is correctly used in the parameters block below)

functions {
matrix toeplitz_matrix(vector x, int M, int N) {
if (num_elements(x) != M + N - 1) {
reject("x must have M + N - 1 elements",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these rejects should be fatal_errors, since the sizes will never change there is no recovery possible

```stan
functions {
matrix symmetric_matrix(vector x, int N) {
matrix[N, N] y = lower_triangular_matrix(x, N);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrix[N, N] y = lower_triangular_matrix(x, N);
matrix[N, N] y = lower_triangular_matrix(x, N); // defined as above

Or any other indication that this is not a built-in and therefore this example is not fully self-contained

```

The transform itself, which takes a vector $v$ of size $\binom{N}{2}$,
creates a skew-symmetric matrix (the `skew_symmetric` function is defined

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
creates a skew-symmetric matrix (the `skew_symmetric` function is defined
creates a skew-symmetric matrix (the `skew_symmetric_matrix` function is defined

* @return The `N` x `N` rotation matrix for which `v` is the basis
*/
matrix special_orthogonal_jacobian(vector v, int N) {
matrix[N, N] S = skew_symmetric(v, N);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
matrix[N, N] S = skew_symmetric(v, N);
matrix[N, N] S = skew_symmetric_matrix(v, N);

Comment on lines +1412 to +1417
{
tuple(matrix[D, D], matrix[D, D]) phi_Gamma
= stationary_var1_jacobian(raw, D);
phi = phi_Gamma.1;
Gamma = phi_Gamma.2;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have tuple unpacking

Suggested change
{
tuple(matrix[D, D], matrix[D, D]) phi_Gamma
= stationary_var1_jacobian(raw, D);
phi = phi_Gamma.1;
Gamma = phi_Gamma.2;
}
(phi, Gamma) = stationary_var1_jacobian(raw, D);

Comment on lines +1424 to +1430
covariance `Gamma`. These need to be pulled out of the tuple. This
is one function returning a tuple because there is shared work. The
extra braces mean that `phi_Gamma` is no longer a top-level
`transformed parameters` variable and thus will not be saved in the
output (it would be redundant). The model could have been written
directly in terms of `phi_Gamma.1` and `phi_Gamma.2`, but it's easier
to follow as written. Note that `phi` is used in its transposed form

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which makes this explanation redundant


## Matrices matching known margins

Suppose $X$ is an $M \times N$ matrix $X$, the marginals of which are

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Suppose $X$ is an $M \times N$ matrix $X$, the marginals of which are
Suppose $X$ is an $M \times N$ matrix, the marginals of which are

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants