Struct LogProbVector

Source
pub struct LogProbVector { /* private fields */ }
Expand description

The representation of a probability vector in log-space

Log-space manipulation of probabilitys is stabler regarding vectors with values very close to 0 or 1. This uses the natural logarithm (base e).

The content of this log-proba vector may not be normalized: adding a constant value to all entries of the vector does not change the normalized probability it represents.

Implementations§

Source§

impl LogProbVector

Source

pub fn uniform(n: usize) -> LogProbVector

Create an unnormalized log-probability vector representing an uniform distribution

Source

pub fn deterministic(n: usize, i: usize) -> LogProbVector

Create an unnormalized log-probability vector representing a deterministic distribution choosing value i from the n possible

If i >= n, this returns a vector assigning 0 probability to every value.

Source

pub fn from_log_probabilities(log_probabilities: Array1<f32>) -> LogProbVector

Wrap an array of log-probabilities into a log-probability vector

Source

pub fn log_probabilities(&self) -> ArrayView1<'_, f32>

Access the underlying array of log-probas

Source

pub fn as_probabilities(&self) -> Array1<f32>

Get the normalized probabilities represented by this log-probability vector

Examples found in repository?
examples/simple_net.rs (line 76)
3fn main() {
4    let mut net = BayesNet::new();
5
6    // create a small graph from the classic example:
7    //
8    // +----------+          +----------------------+
9    // | It rains | -------> | Sprinkler is running |
10    // +----------+          +----------------------+
11    //       |                 |
12    //       +----+     +------+
13    //            |     |
14    //            v     v
15    //        +--------------+
16    //        | Grass is Wet |
17    //        +--------------+
18
19    // Rain has no parents, it is a prior
20    // We have P(not Rain) = 0.8, P(Rain) = 0.8
21    let rain = net.add_node_from_probabilities(&[], ndarray::Array1::from(vec![0.8, 0.2]));
22
23    // Sprinkler has a parent (Rain)
24    // We have P(not Sprinkler | not Rain) = 0.60, P(not Sprinkler | Rain) = 0.99
25    //         P(    Sprinkler | not Rain) = 0.40, P(    Sprinkler | Rain) = 0.01
26    let sprinkler = net.add_node_from_probabilities(
27        &[rain],
28        ndarray::Array2::from(vec![[0.60, 0.99], [0.40, 0.01]]),
29    );
30
31    // Wet has 2 parents (Rain and Sprinkler)
32    // We have P(not Wet | not Rain, not Sprinkler) = 1.0, P(not Wet | not Rain, Sprinkler) = 0.1
33    //         P(not Wet | Rain,     not Sprinkler) = 0.2, P(not Wet | Rain,     Sprinkler) = 0.01
34    //         P(    Wet | not Rain, not Sprinkler) = 0.0, P(    Wet | not Rain, Sprinkler) = 0.9
35    //         P(    Wet | Rain,     not Sprinkler) = 0.8, P(    Wet | Rain,     Sprinkler) = 0.99
36    let wet = net.add_node_from_probabilities(
37        &[rain, sprinkler],
38        ndarray::Array3::from(vec![[[1.0, 0.1], [0.2, 0.01]], [[0.0, 0.9], [0.8, 0.99]]]),
39    );
40    /*
41        // We can now do some inferences
42        // First, compute the marginal probabilities of the network without any evidence
43        net.reset_state();
44        net.set_evidence(&[]);
45        println!("===== raw marginal probabilities =====");
46        for _ in 1..10 {
47            // this net converges pretty quickly
48            net.step();
49        }
50        let beliefs = net.beliefs();
51        println!(
52            "    P(Rain)      = {:.2}",
53            beliefs[rain].as_probabilities()[1]
54        );
55        println!(
56            "    P(Sprinkler) = {:.2}",
57            beliefs[sprinkler].as_probabilities()[1]
58        );
59        println!(
60            "    P(Wet)       = {:.2}",
61            beliefs[wet].as_probabilities()[1]
62        );
63    */
64    println!();
65    println!("===== marginal probabilities assuming the grass is wet =====");
66    // Now, assuming we see the grass we, what can we infer from this ?
67    net.reset_state();
68    net.set_evidence(&[(wet, 1)]);
69    for i in 1..21 {
70        // this net is slower to converge
71        net.step();
72        let beliefs = net.beliefs();
73        println!("After iteration {}", i);
74        println!(
75            "    P(Rain | Wet)      = {:.2}",
76            beliefs[rain].as_probabilities()[1]
77        );
78        println!(
79            "    P(Sprinkler | Wet) = {:.2}",
80            beliefs[sprinkler].as_probabilities()[1]
81        );
82        println!(
83            "    P(Wet | Wet)       = {:.2}",
84            beliefs[wet].as_probabilities()[1]
85        );
86    }
87    /*
88        println!();
89        println!("===== marginal probabilities assuming the sprinkler is running =====");
90        // Evidence doesn't need to be at the last node
91        net.reset_state();
92        net.set_evidence(&[(sprinkler, 1)]);
93        for _ in 1..10 {
94            // this one is quick to converge too
95            net.step();
96        }
97        let beliefs = net.beliefs();
98        println!(
99            "    P(Rain | Sprinkler)      = {:.2}",
100            beliefs[rain].as_probabilities()[1]
101        );
102        println!(
103            "    P(Sprinkler | Sprinkler) = {:.2}",
104            beliefs[sprinkler].as_probabilities()[1]
105        );
106        println!(
107            "    P(Wet | Sprinkler)       = {:.2}",
108            beliefs[wet].as_probabilities()[1]
109        );
110
111        println!();
112        println!("===== marginal probabilities assuming it's not rainning =====");
113        // Evidence can even be at the prior !
114        net.reset_state();
115        net.set_evidence(&[(rain, 0)]);
116        for _ in 1..10 {
117            // this one is quick to converge too
118            net.step();
119        }
120        let beliefs = net.beliefs();
121        println!(
122            "    P(Rain | not Rain)      = {:.2}",
123            beliefs[rain].as_probabilities()[1]
124        );
125        println!(
126            "    P(Sprinkler | not Rain) = {:.2}",
127            beliefs[sprinkler].as_probabilities()[1]
128        );
129        println!(
130            "    P(Wet | not Rain)       = {:.2}",
131            beliefs[wet].as_probabilities()[1]
132        );
133    */
134}
Source

pub fn renormalize(&mut self)

Renormalize the log-probability vector so that its content represent exactly the log of a normalized probability distribution.

Source

pub fn prod(&mut self, other: &LogProbVector)

Multiply the given log-probability vector into this one.

NB: Multiplication is done in probability space, hence the log-probabilities are summed As a result, the log-probability vector will no longer be normalized if it was.

Source

pub fn reset(&mut self)

Resets this log-probas vector to a uniform distribution

Trait Implementations§

Source§

impl Clone for LogProbVector

Source§

fn clone(&self) -> LogProbVector

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LogProbVector

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.