We’re very happy to announce the release of version 1.0.0 of BridgeStan.
What is BridgeStan?
To quote from the documentation,
BridgeStan provides efficient in-memory access through Python, Julia, and R to the methods of a Stan model, including log densities, gradients, Hessians, and constraining and unconstraining transforms.
In other words, BridgeStan lets you define a model in Stan, compile it to C++, then access it efficiently through Python, Julia, or R. BridgeStan does not perform any kind of inference. It only provides a hook into log density, gradient and Hessian evaluation as well as the constraining and unconstraining transforms.
BridgeStan provides the model accessibility features of PyStan and RStan to users of our lightweight CmdStan interfaces, cmdstanr and cmdstanpy in a up-to-date (with Stan), performant, easy-to-install, and lightweight package.
BridgeStan also provides a simple C client, which should make it easier to interface with other client languages beyond R, Python, and Julia.
What’s it good for?
The primary goal for BridgeStan is to support both algorithm research and application development.
For example, @YifanZhou built an implementation of zero-variance control variates in Python on top of BridgeStan, which is available through GitHub at zhouyifan233/ControlVariates.
Documentation
The user and developer facing documentation, is here:
- Documentation:
https://roualdes.github.io/bridgestan/
The documentation explains how to install BridgeStan on Windows, Linux, or Mac OS X, and how to use it through Python, R, Julia, or C. It also provides technical details and additional links for testing and documentation generation for developers who would like to contribute to BridgeStan.
Source code repository
The source code is all here:
- GitHub repo:
https://github.com/roualdes/bridgestan
The code is pretty simple—the harder part was getting all the builds, dependencies, and config right.
How does it work?
Like RStan and the original PyStan, BridgeStan uses a client-specific foreign function interface to communicate between the client language (R, Python, or Julia) and C++ (or C). That means there’s no additional processes to manage and no communication overhead as all of the data is shared with the client language in a single process. It also imports the makefile magic from CmdStan to manage Stan model transpiration to C++ and then the compilation of that C++.
It works through a combination of makefile magic and connections to Python, Julia, and R at the lowest integration level. That is, rather than using a high-level interface like Rcpp (R) or Cython (Python), we use the .C interface to R and the ctypes interface to Python. The advantage of this is fewer dependencies and easier installation.
There are some more details in the foreign function interface overview.
There are dependencies on stanc3 (the transpiler that converts Stan to C++), stan (which implements the basic model interface), and the Stan math library which implements autodiff, constrained variable transforms, and all the special functions.
Hessians are implemented following RStan using central finite differences over gradients. Clients can also configure BridgeStan to use the faster and more accurate autodiff-based Hessian calculations in cases where all of the functions are supported for higher-order differentiation (our implicit functions like ODE integrators do not support autodiff for second derivatives yet).
History
The BridgeStan project was started by @roualdes as a Julia interface, and then @WardBrian and I got involved. BridgeStan descends directly from @syclik’s and @dmuck’s ReddingStan, which is an out-of-process server-based approach to the same problem.
ReddingStan was in turn motivated by httpstan
, which is the foundation of PyStan3; both httpstan and PyStan3 are primarily maintained by @ariddell with help from @ahartikainen and @mjcarter.
The major difference between BridgeStan and both ReddingStan and httpstan is that BridgeStan runs in memory through a foreign function interface rather than as a server. In this way, BridgeStan is closer in spirit to RStan and the original pre-httpstan design of PyStan, both of which accessed models in memory through a (higher-level) foreign function interface.
Not an official Stan project
We intentionally decided to not try to make this an official Stan project in order to maintain control through the design phase. This was mainly at my urging, because I’ve been very frustrated in the past being overruled on all of our interface designs.
We might be amenable to making it an official Stan project at a later date.