10 stable releases

2.5.0 Jun 18, 2024
2.4.1 Apr 17, 2024
2.4.0 Mar 25, 2024
2.3.0 Dec 11, 2023
2.1.1 Jun 30, 2023

#131 in Science

Download history 3/week @ 2024-08-08 16/week @ 2024-08-22 10/week @ 2024-08-29 2/week @ 2024-09-12 6/week @ 2024-09-19 17/week @ 2024-09-26 22/week @ 2024-10-03 28/week @ 2024-10-10 27/week @ 2024-10-17 5/week @ 2024-10-24 14/week @ 2024-10-31 26/week @ 2024-11-07 99/week @ 2024-11-14 5/week @ 2024-11-21

144 downloads per month

BSD-3-Clause

37KB
655 lines

BridgeStan from Rust

View the BridgeStan documentation on Github Pages.

This is a Rust wrapper for BridgeStan. It allows users to evaluate the log likelihood and related functions for Stan models natively from Rust.

Internally, it relies on bindgen and libloading.

Compiling the model

The Rust wrapper has the ability to compile Stan models by invoking the make command through the compile_model function.

This requires a C++ toolchain and a copy of the BridgeStan source code. The source code can be downloaded automatically by enabling the download-bridgestan-src feature and calling download_bridgestan_src. Alternatively, the path to the BridgeStan source code can be provided manually.

For safety reasons all Stan models need to be built with STAN_THREADS=true. This is the default behavior in the compile_model function, but may need to be set manually when compiling the model in other contexts.

If STAN_THREADS was not specified while building the model, the Rust wrapper will throw an error when loading the model.

Usage

Run this example with cargo run --example=example.

use std::ffi::CString;
use std::path::{Path, PathBuf};
use bridgestan::{BridgeStanError, Model, open_library, compile_model};

// The path to the Stan model
let path = Path::new(env!["CARGO_MANIFEST_DIR"])
    .parent()
    .unwrap()
    .join("test_models/simple/simple.stan");

// You can manually set the BridgeStan src path or
// automatically download it (but remember to
// enable the download-bridgestan-src feature first)
let bs_path: PathBuf = "..".into();
// let bs_path = bridgestan::download_bridgestan_src().unwrap();

// The path to the compiled model
let path = compile_model(&bs_path, &path, &[], &[]).expect("Could not compile Stan model.");
println!("Compiled model: {:?}", path);

let lib = open_library(path).expect("Could not load compiled Stan model.");

// The dataset as json
let data = r#"{"N": 7}"#;
let data = CString::new(data.to_string().into_bytes()).unwrap();

// The seed is used in case the model contains a transformed data section
// that uses rng functions.
let seed = 42;

let model = match Model::new(&lib, Some(data), seed) {
    Ok(model) => model,
    Err(BridgeStanError::ConstructFailed(msg)) => {
        panic!("Model initialization failed. Error message from Stan was {msg}")
    }
    Err(e) => {
        panic!("Unexpected error:\n{e}")
    }
};

let n_dim = model.param_unc_num();
assert_eq!(n_dim, 7);
let point = vec![1f64; n_dim];
let mut gradient_out = vec![0f64; n_dim];
let logp = model.log_density_gradient(&point[..], true, true, &mut gradient_out[..])
    .expect("Stan failed to evaluate the logp function.");
// gradient_out contains the gradient of the logp density

Dependencies

~0.5–12MB
~150K SLoC