← Back to Priors
Custom Priors

Custom Priors

Define your own log-density via two prefix forms: expression: and table:. Use them anywhere a prior string is accepted: random-effect hyperparameters, likelihood hyperparameters, or group-correlation hyperparameters.

Two Forms in One Place

FormUse whenDensity at \(\theta\)
expression:<code> You can write the log-density as a single mathematical expression. Evaluated symbolically at runtime, using the variable theta on the internal scale.
table: x1 ... xn | l1 ... ln You have the log-density tabulated on a grid (simulation, conjugate analysis, etc.). Linear interpolation between the supplied knots (xi, li).

Both forms are passed straight through to the C engine. pyinla does not validate the inner content (it cannot, generally); the grammar limits below come from the engine itself.

The expression: Form

The C engine has a single-expression evaluator, not a full R interpreter. Your expression must:

Verified Working Forms

PatternExample
Polynomial / quadratic-theta * theta / 2
Shifted normal-(theta - 2) * (theta - 2) / 2
Absolute value (Laplace)-abs(theta)
Constant (improper flat)0
Mixed math + exp-0.00005 * exp(theta) + theta
Trig + loglog(cos(theta/4)^2 + 0.1) - 0.5*theta^2
Standard math functionslog, exp, sqrt, abs, sin, cos, tan, ^
Arithmetic operators+   -   *   /   ^

Not Supported

PatternWhy
if (theta < 0) -theta^2 else -theta^2 / 4 No conditionals or comparison operators.
{ s <- exp(theta); -log(s) - s } No multi-statement blocks or local assignments.
Calls to user-defined R functions Only the engine's built-in math functions are recognised.

Workaround: Smooth Instead of Piecewise

If you need a mixture or piecewise feel, build it as a smooth log-sum-exp:

# Mixture of two Gaussians as a smooth log-density
'hyper': [{'prior':
    'expression: log( 0.5*exp(-theta*theta/2) + 0.5*exp(-(theta-3)*(theta-3)/2) )'}]

If you genuinely need step changes or piecewise definitions, switch to table:.

The table: Form

Pass a grid of theta values and the corresponding log pi(theta) values, separated by |:

'hyper': [{'prior': 'table: -3 -1 1 3 | -4.5 -1.1 -1.1 -4.5'}]

Building a Table from Your Own Log-Density

import numpy as np

grid = np.linspace(-8, 8, 101)
logp = -0.5 * grid**2               # standard normal on theta
spec = 'table: ' + ' '.join(map(str, grid)) + ' | ' + ' '.join(map(str, logp))

'hyper': [{'prior': spec}]

Where You Can Use These Forms

Both prefix forms are accepted in every place pyinla takes a prior string:

pyinla's safety layer recognises the prefix and passes the whole string through unchanged; the C engine does the actual evaluation. Whatever the engine accepts, pyinla accepts.