Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: vectorized phi() #3203

Open
ksvanhorn opened this issue Jul 6, 2023 · 3 comments
Open

Feature request: vectorized phi() #3203

ksvanhorn opened this issue Jul 6, 2023 · 3 comments
Labels

Comments

@ksvanhorn
Copy link
Contributor

Stan has a vectorized $\Phi(x)$ (standard cumulative distribution function) but lacks a corresponding vectorized $\varphi(x)$ (standard normal density). You can't get this using std_normal_lpdf(), as it sums the log density values; I'm asking for something that returns a vectorized result.

One use case for a vectorized $\Phi(x)$ is in computing a quasi-hinge function based on $\Phi(x)$:

$h(x) = x \Phi(x) + \varphi(x)$.

This function has range $(0,\infty)$ with $h(x) \to 0$ as $x\to -\infty$, $h(x)/x \to 1$ as $x\to \infty$, and $h'(x) = \Phi(x)$.

@bob-carpenter
Copy link
Contributor

We do have a vectorized erf(), so a standard normal is just a factor of sqrt(2) away. Did you want the same signatures as we provide for erf()? That'd be

vector phi(vector);
row_vector phi(row_vector);
matrix phi(matrix);
real[] phi(real[]);
...

There are other feature requests asking us to supply vectorized versions of all of our probability functions. They're useful for things like log likelihoods for leave-one-out cross-validation.

@rok-cesnovar
Copy link
Member

rok-cesnovar commented Jul 7, 2023

The Phi function supports the following signatures in the latest few versions:

Phi(int) => real
Phi(real) => real
Phi(vector) => vector
Phi(row_vector) => row_vector
Phi(matrix) => matrix
Phi(array[] int) => array[] real
Phi(array[] real) => array[] real
Phi(array[] vector) => array[] vector
Phi(array[] row_vector) => array[] row_vector
Phi(array[] matrix) => array[] matrix
Phi(array[,] int) => array[,] real
Phi(array[,] real) => array[,] real
Phi(array[,] vector) => array[,] vector
Phi(array[,] row_vector) => array[,] row_vector
Phi(array[,] matrix) => array[,] matrix
Phi(array[,,] int) => array[,,] real
Phi(array[,,] real) => array[,,] real
Phi(array[,,] vector) => array[,,] vector
Phi(array[,,] row_vector) => array[,,] row_vector
Phi(array[,,] matrix) => array[,,] matrix
Phi(array[,,,] int) => array[,,,] real
Phi(array[,,,] real) => array[,,,] real
Phi(array[,,,] vector) => array[,,,] vector
Phi(array[,,,] row_vector) => array[,,,] row_vector
Phi(array[,,,] matrix) => array[,,,] matrix
Phi(array[,,,,] int) => array[,,,,] real
Phi(array[,,,,] real) => array[,,,,] real
Phi(array[,,,,] vector) => array[,,,,] vector
Phi(array[,,,,] row_vector) => array[,,,,] row_vector
Phi(array[,,,,] matrix) => array[,,,,] matrix
Phi(array[,,,,,] int) => array[,,,,,] real
Phi(array[,,,,,] real) => array[,,,,,] real
Phi(array[,,,,,] vector) => array[,,,,,] vector
Phi(array[,,,,,] row_vector) => array[,,,,,] row_vector
Phi(array[,,,,,] matrix) => array[,,,,,] matrix
Phi(array[,,,,,,] int) => array[,,,,,,] real
Phi(array[,,,,,,] real) => array[,,,,,,] real
Phi(array[,,,,,,] vector) => array[,,,,,,] vector
Phi(array[,,,,,,] row_vector) => array[,,,,,,] row_vector
Phi(array[,,,,,,] matrix) => array[,,,,,,] matrix

@bob-carpenter
Copy link
Contributor

Thanks @rok-cesnovar. This is the list you get from using the automatic vectorization of a unary function, which will be an easy way to implement this. Better to provide an analytic gradient for reverse mode. Callingstd_normal_lpdf function to implement unary standard normal is probably too heavy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants