pub struct BayesNet { /* private fields */ }
Expand description
Representation of a Bayesian Network
Once built by adding the nodes one by one, you can use it for inference computation on the graph given some evidence.
Implementations§
Source§impl BayesNet
impl BayesNet
Sourcepub fn new() -> BayesNet
pub fn new() -> BayesNet
Create a new empty Bayesian Network
Examples found in repository?
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}
Sourcepub fn add_node_from_probabilities<D: Dimension + RemoveAxis>(
&mut self,
parents: &[usize],
probabilities: Array<f32, D>,
) -> usize
pub fn add_node_from_probabilities<D: Dimension + RemoveAxis>( &mut self, parents: &[usize], probabilities: Array<f32, D>, ) -> usize
Add a new node to the network
You need to specify the list of its parents, and an array of probabilities representing p(x | parents)
.
If the parents are (p1, ... pk)
, the shape of the array should thus be: (N, N_p1, ... N_pk)
, where
N
is the number of possible values for the current variables, and N_pi
is the number of values of
parent pi
.
If the node has no parents, the propabilities must be single-dimenstionnal and represents a prior.
All values of probabilities should be finite, but the probabilities array does not need to be normalized, as it will be during the construction process.
Examples found in repository?
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}
Sourcepub fn add_node_from_log_probabilities<D: Dimension + RemoveAxis>(
&mut self,
parents: &[usize],
log_probabilities: Array<f32, D>,
) -> usize
pub fn add_node_from_log_probabilities<D: Dimension + RemoveAxis>( &mut self, parents: &[usize], log_probabilities: Array<f32, D>, ) -> usize
Add a new node to the network from log-probabilities
Same as add_node_from_probabilities
, but the input is in the form of log-probabilities, for greated precision.
All values of log-probas should be strictly smaller than +inf
. -inf
is valid and represents a
probability of 0. The probabilities array does not need to be normalized, as it will be during the construction
process. For example, the log-vector [0.0, -inf]
will represent a vector of probabilities of [1.0, 0.0]
.
Log-probabilities are intepreted as computed with the natural logarithm (base e).
Sourcepub fn set_evidence(&mut self, evidence: &[(usize, usize)])
pub fn set_evidence(&mut self, evidence: &[(usize, usize)])
Sets the evidence for the network
Input is interpreted as a list of (node_id, node_value)
. Out-of-range evidence is not checked, but
will result into a probability of 0
.
Examples found in repository?
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}
Sourcepub fn reset_state(&mut self)
pub fn reset_state(&mut self)
Resets the internal state of the inference algorithm, to begin a new inference
Examples found in repository?
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}
Sourcepub fn beliefs(&self) -> Vec<LogProbVector>
pub fn beliefs(&self) -> Vec<LogProbVector>
Compute the current state belief of each node according to the current internal messages
Examples found in repository?
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}
Sourcepub fn step(&mut self)
pub fn step(&mut self)
Compute one step of the Loopy Belief Propagation Algorithm
The algorithm can be run for any number of steps. it is up to you to decide when to stop.
A classic stopping criterion is when the yielded beliefs stop significantly changing.
Examples found in repository?
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}
Auto Trait Implementations§
impl Freeze for BayesNet
impl RefUnwindSafe for BayesNet
impl Send for BayesNet
impl Sync for BayesNet
impl Unpin for BayesNet
impl UnwindSafe for BayesNet
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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