I’d like to announce the opensource release of Chronikis (krohNEEkees), a specialpurpose language for creating Bayesian timeseries models, available here:
[http://opensource.adobe.com/Chronikis/](http://opensource.adobe.com/Chronikis/)
Stan is the target language for the Chronikis compiler, and use from within R is supported via rstan. The class of models currently supported are linear statespace models (a.k.a. dynamic linear models).
As a simple example, here is a Chronikis program for a randomwalk model with added independent observation noise:
def main(sigma_q_scale, sigma_h_scale: real{0.0,},
mu_a: real, sigma_a: real{0.0,})
=
sigma_q ~ half_cauchy(sigma_q_scale);
sigma_h ~ half_normal(sigma_h_scale);
accum(wn(sigma_q), mu_a, sigma_a) + wn(sigma_h)
In the above, sigma_q_scale, sigma_h_scale, mu_a, and sigma_a are all prior parameters that are supplied when a model is created and estimated. The first two lines express priors on sigma_q and sigma_h, and the last line is an expression whose “value” is a time series model, that is, a probability distribution over temporal sequences.
The subexpression
wn(sigma_h)
means “white noise” with mean 0 and variance sigma_h^2. The subexpression
accum(wn(sigma_q), mu_a, sigma_a)
(“accum” is short for “accumulate”) indicates a time series model for which

the initial value y[0] is drawn from a normal distribution with mean mu_a and variance sigma_a^2, and

the differences y[t]  y[t1] are independent normal draws with mean 0 and variance sigma_q^2.
Note that Chronikis programs are fully declarative. It is also statically typed, but all types other than the parameters of main() are inferred. Type inference is bottomup; I have not attempted to implement anything like the HindleyMilner type inference used in the Haskell and the ML family of programming languages.
The Chronikis compiler translates the above into the following Stan program:
functions {
}
data {
int<lower = 1> N;
vector[N] y;
real<lower = 0.0> sigma_q_scale_;
real<lower = 0.0> sigma_h_scale_;
real mu_a_;
real<lower = 0.0> sigma_a_;
}
transformed data {
matrix[1, N] yy = to_matrix(y');
vector[1] Z_0_ = rep_vector(1.0, 1);
matrix[1, 1] T_0_ = rep_matrix(1.0, 1, 1);
vector[1] a0_0_ = rep_vector(mu_a_, 1);
matrix[1, 1] P0_0_ = rep_matrix(square(sigma_a_), 1, 1);
}
parameters {
real<lower = 0.0> raw_0_;
real<lower = 0.0> raw_1_;
}
transformed parameters {
real sigma_q_ = raw_0_ * sigma_q_scale_;
real sigma_h_ = raw_1_ * sigma_h_scale_;
}
model {
real H_0_ = square(sigma_h_);
matrix[1, 1] Q_0_ = rep_matrix(square(sigma_q_), 1, 1);
raw_0_ ~ cauchy(0.0, 1.0) T[0.0, ];
raw_1_ ~ normal(0.0, 1.0) T[0.0, ];
yy ~ gaussian_dlm_obs(to_matrix(Z_0_), T_0_, rep_vector(H_0_, 1), Q_0_, a0_0_, P0_0_);
}
A few notes:

Instead of requiring the user to specify the matrices defining the linear statespace model, Chronikis provides an algebra of timeseries models which it transforms into a symbolic expression describing the equivalent linear statespace model.

The compiler infers the shapes and bounds of all variables, starting with the shapes and bounds of the parameters of main().

The compiler automatically reparameterizes inferred variables to use noncentered parameterization, and assigns variables to the appropriate Stan model blocks.

The Chronikis compiler is implemented in Haskell.
This current release is a very early version, and is still missing some obvious functionality. I welcome any feedback that (potential) users may provide.
Thanks to my employer, Adobe Inc., for allowing me to opensource this project.