1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/// # Create a markov chain by doing markov steps
pub trait MarkovChain<S, Res> {
/// * undo a markov step, return result-state
/// * if you want to undo more than one step
/// see [`undo_steps`](#method.undo_steps)
fn undo_step(&mut self, step: &S) -> Res;
/// * undo a markov, **panic** on invalid result state
/// * for undoing multiple steps see [`undo_steps_quiet`](#method.undo_steps_quiet)
fn undo_step_quiet(&mut self, step: &S);
/// # Markov step
/// * use this to perform a markov step step
/// * for doing multiple markov steps at once, use [`m_steps`](#method.m_steps)
fn m_step(&mut self) -> S;
/// # Markov steps
/// * use this to perform multiple markov steps at once
/// * steps can be used to undo the steps with `self.undo_steps(steps)`
/// * `steps` will be emptied before step is performed
#[inline]
fn m_steps(&mut self, count: usize, steps: &mut Vec<S>) {
steps.clear();
steps.extend((0..count)
.map(|_| self.m_step())
);
}
/// # Markov steps without return
/// * use this to perform multiple markov steps at once
/// * only use this if you **know** that you do **not** want to undo the steps
/// * you cannot undo this steps, but therefore it does not need to allocate a vector
/// for undoing steps
fn m_steps_quiet(&mut self, count: usize)
{
for _ in 0..count {
self.m_step();
}
}
/// # Accumulating markov step
/// * this calculates something while performing the markov chain, e.g., the current energy,
/// which can be more efficient then calculating it from scratch afterwards
#[inline]
fn m_step_acc<Acc, AccFn>(&mut self, acc: &mut Acc, mut acc_fn: AccFn) -> S
where AccFn: FnMut(&Self, &S, &mut Acc)
{
let s = self.m_step();
acc_fn(self, &s, acc);
s
}
/// # Accumulating markov steps
/// * this calculates something while performing the markov chain, e.g., the current energy
/// which can be more efficient then calculating it from scratch afterwards
#[inline]
fn m_steps_acc<Acc, AccFn>
(
&mut self,
count: usize,
steps: &mut Vec<S>,
acc: &mut Acc,
mut acc_fn: AccFn
)
where AccFn: FnMut(&Self, &S, &mut Acc)
{
steps.clear();
steps.extend(
(0..count)
.map(|_| self.m_step_acc(acc, &mut acc_fn))
);
}
/// # Accumulating markov steps
/// * this calculates something while performing the markov chain, e.g., the current energy
/// which can be more efficient then calculating it from scratch afterwards
/// * quiet step, i.e., you will not be able to undo the step
#[inline]
fn m_steps_acc_quiet<Acc, AccFn>(&mut self, count: usize, acc: &mut Acc, mut acc_fn: AccFn)
where AccFn: FnMut(&Self, &S, &mut Acc)
{
for _ in 0..count{
let _ = self.m_step_acc(acc, &mut acc_fn);
}
}
/// # Undo markov steps
/// * Note: uses undo_step in correct order and returns result
/// ## Important:
/// * look at specific implementation of `undo_step`, every thing mentioned there applies to each step
fn undo_steps(&mut self, steps: &[S], res: &mut Vec<Res>) {
res.clear();
res.extend(
steps.iter()
.rev()
.map(|step| self.undo_step(step))
);
}
/// # Undo markov steps
/// * Note: uses `undo_step_quiet` in correct order
/// ## Important:
/// * look at specific implementation of `undo_step_quiet`, every thing mentioned there applies to each step
fn undo_steps_quiet(&mut self, steps: &[S]) {
steps.iter()
.rev()
.for_each( |step| self.undo_step_quiet(step));
}
/// # Function called whenever the steps are accepted.
/// *You can use it to create the acceptance statistics if
/// you move a variety of different moves
/// * If you use the default implementation this will be a optimized out
#[inline]
fn steps_accepted(&mut self, _steps: &[S])
{
}
/// # Function called whenever the steps are rejected.
/// * You can use it to create the acceptance statistics if
/// you move a variety of different moves
/// * If you use the default implementation this will be a optimized out
#[inline]
fn steps_rejected(&mut self, _steps: &[S])
{
}
}
/// For easy sampling of your ensemble
pub trait SimpleSample{
/// # Randomizes self according to model
/// * this is intended for creation of initial sample
/// * used in [`simple_sample`](#method.simple_sample)
/// and [`simple_sample_vec`](#method.simple_sample_vec)
fn randomize(&mut self);
/// # do the following `times` times:
/// 1) `f(self)`
/// 2) `self.randomize()`
fn simple_sample<F>(&mut self, times: usize, mut f: F)
where F: FnMut(&Self)
{
for _ in 0..times {
f(self);
self.randomize();
}
}
/// # do the following `times` times:
/// 1) `res = f(self)`
/// 2) `self.randomize()`
/// ## res is collected into Vector
fn simple_sample_vec<F, G>(&mut self, times: usize, mut f: F) -> Vec<G>
where F: FnMut(&Self) -> G
{
let mut vec = Vec::with_capacity(times);
for _ in 0..times {
vec.push(f(self));
self.randomize();
}
vec
}
}
/// # Access internal random number generator
pub trait HasRng<Rng>
where Rng: rand::Rng
{
/// # Access RNG
/// If, for some reason, you want access to the internal random number generator: Here you go
fn rng(&mut self) -> &mut Rng;
/// # If you need to exchange the internal rng
/// * swaps internal random number generator with `rng`
fn swap_rng(&mut self, rng: &mut Rng);
}