use ferric::make_model;
#[test]
fn sensor_fusion() {
make_model! {
name sensor_fusion;
use ferric::distributions::Normal;
let true_mean : f64 ~ Normal::new( 0.0, 3.0 );
let sensor_1 : f64 ~ Normal::new( true_mean, 1.0 );
let sensor_2 : f64 ~ Normal::new( true_mean, 1.0 );
observe sensor_1;
observe sensor_2;
query true_mean;
};
let model = sensor_fusion::Model {
sensor_1: 1.5,
sensor_2: 2.5,
};
let num_samples = 100000;
let mut mean_vals = Vec::with_capacity(num_samples);
let mut log_weights = Vec::with_capacity(num_samples);
for ws in model.weighted_sample_iter().take(num_samples) {
mean_vals.push(ws.sample.true_mean);
log_weights.push(ws.log_weight);
}
let post_mean = ferric::weighted_mean(&mean_vals, &log_weights);
let post_std = ferric::weighted_std(&mean_vals, &log_weights);
println!("posterior mean = {:.4} std = {:.4}", post_mean, post_std);
let mean_ans = 36.0_f64 / 19.0; let std_ans = (9.0_f64 / 19.0).sqrt();
assert!(
(post_mean - mean_ans).abs() < 0.1,
"posterior mean {:.4} not close to analytical {:.4}",
post_mean,
mean_ans
);
assert!(
(post_std - std_ans).abs() < 0.1,
"posterior std {:.4} not close to analytical {:.4}",
post_std,
std_ans
);
}