5 个版本

0.2.1 2020年7月13日
0.1.3 2020年4月6日
0.1.2 2020年4月2日
0.1.1 2020年3月24日
0.1.0 2020年3月24日

#1335 in 数学

MIT/Apache

53KB
950 代码行

markovian

随机过程的模拟。

目标

作为 rand crate 的扩展,用于子随机马尔可夫过程。

主要功能

  • 轻松构建马尔可夫过程,包括
    • 离散时间
    • 连续时间(指数时钟)
  • 类型无关

变更日志

请参阅 变更日志

贡献

非常感谢您的贡献。请随时提交问题或拉取请求。请注意,任何提交给项目包含的贡献都将根据双许可(MIT 和 Apache-2.0)的条款进行许可。


lib.rs:

(子-)随机过程的模拟。

目标

作为 rand crate 的扩展,用于子随机过程。

示例

离散时间

在整数上的随机游走。

let init_state: i32 = 0;
let transition = |state: &i32| raw_dist![(0.5, state + 1), (0.5, state - 1)];
let rng = thread_rng();
let mut mc = markovian::MarkovChain::new(init_state, transition, rng);

分支过程

使用密度 p(0) = 0.3,p(1) = 0.4,p(2) = 0.3 构建。

let init_state: u32 = 1;
let base_distribution = raw_dist![(0.3, 0), (0.4, 1), (0.3, 2)];
let rng = thread_rng();
let mut branching_process = markovian::BranchingProcess::new(init_state, base_distribution, rng);

连续时间

使用指数时间进行每个转换的整数上的随机游走。

let init_state: i32 = 0;
struct MyTransition;
impl markovian::Transition<i32, (f64, i32)> for MyTransition {
    fn sample_from<R: ?Sized>(&self, state: &i32, rng: &mut R) -> (f64, i32)
    where
        R: Rng
    {
        let time = Exp::new(2.0).unwrap().sample(rng);
        let step = Uniform::from(0..=1).sample(rng) * 2 - 1;
        (time, state + step)
    }
}
let transition = MyTransition;
let rng = thread_rng();
let mut mc = markovian::TimedMarkovChain::new(init_state, transition, rng);

备注

所有方法都是 inline,这是有意为之。

下面描述了使用 crate 的非平凡方式,包括时间依赖性、连续空间和非马尔可夫过程。

时间依赖性

将时间作为过程状态的一部分。

示例

一个随时间推移越来越向右移动的整数上的随机游走。

let init_state: (usize, i32) = (0, 0);
let transition = |(time, state): &(usize, i32)| raw_dist![
    (0.6 - 1.0 / (time + 2) as f64, (time + 1, state + 1)),
    (0.4 + 1.0 / (time + 2) as f64, (time + 1, state - 1))
];
let rng = thread_rng();
let mut mc = markovian::MarkovChain::new(init_state, &transition, rng);

// Take a sample of 10 elements 
mc.take(10).map(|(_, state)| state).collect::<Vec<i32>>();

连续空间

随机化转换:返回一个随机元素和一个概率为 1

示例

具有可变步长的实数线上的随机游走。

let init_state: f64 = 0.0;
struct MyTransition;
impl markovian::Transition<f64, f64> for MyTransition {
    fn sample_from<R: ?Sized>(&self, state: &f64, rng: &mut R) -> f64
    where
        R: Rng
    {
        let step = Exp::new(2.0).unwrap().sample(rng);
        state + step
    }
}
let transition = MyTransition;
let rng = thread_rng();
let mut mc = markovian::MarkovChain::new(init_state, transition, rng);
mc.next();
 
// current_state is positive 
assert!(mc.state().unwrap() > &0.0);

非马尔可夫

在状态中包含历史。例如,而不是 i32,使用 Vec<i32>

示例

一个以非马尔可夫方式吸引到零的整数上的随机游走。

let init_state: Vec<i32> = vec![0];
let transition = |state: &Vec<i32>| {
    // New possible states
    let mut right = state.clone();
    right.push(state[state.len() - 1] + 1);
    let mut left = state.clone();
    left.push(state[state.len() - 1] - 1);

    // Some non markovian transtion
    let path_stadistic: i32 = state.iter().sum();
    if path_stadistic.is_positive() {
        raw_dist![
            (1.0 / (path_stadistic.abs() + 1) as f64, right), 
            (1.0 - 1.0 / (path_stadistic.abs() + 1) as f64, left)
        ]
    } else {
        raw_dist![
            (1.0 - 1.0 / (path_stadistic.abs() + 1) as f64, right), 
            (1.0 / (path_stadistic.abs() + 1) as f64, left)
        ]
    }
};
let rng = thread_rng();
let mut mc = markovian::MarkovChain::new(init_state, transition, rng);
 
// state has history
mc.next();
assert_eq!(mc.state().unwrap().len(), 2);

依赖项

~1.1–1.7MB
~35K SLoC