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
use loopybayesnet::BayesNet;
fn main() {
let mut net = BayesNet::new();
// create a small graph from the classic example:
//
// +----------+ +----------------------+
// | It rains | -------> | Sprinkler is running |
// +----------+ +----------------------+
// | |
// +----+ +------+
// | |
// v v
// +--------------+
// | Grass is Wet |
// +--------------+
// Rain has no parents, it is a prior
// We have P(not Rain) = 0.8, P(Rain) = 0.8
let rain = net.add_node_from_probabilities(&[], ndarray::Array1::from(vec![0.8, 0.2]));
// Sprinkler has a parent (Rain)
// We have P(not Sprinkler | not Rain) = 0.60, P(not Sprinkler | Rain) = 0.99
// P( Sprinkler | not Rain) = 0.40, P( Sprinkler | Rain) = 0.01
let sprinkler = net.add_node_from_probabilities(
&[rain],
ndarray::Array2::from(vec![[0.60, 0.99], [0.40, 0.01]]),
);
// Wet has 2 parents (Rain and Sprinkler)
// We have P(not Wet | not Rain, not Sprinkler) = 1.0, P(not Wet | not Rain, Sprinkler) = 0.1
// P(not Wet | Rain, not Sprinkler) = 0.2, P(not Wet | Rain, Sprinkler) = 0.01
// P( Wet | not Rain, not Sprinkler) = 0.0, P( Wet | not Rain, Sprinkler) = 0.9
// P( Wet | Rain, not Sprinkler) = 0.8, P( Wet | Rain, Sprinkler) = 0.99
let wet = net.add_node_from_probabilities(
&[rain, sprinkler],
ndarray::Array3::from(vec![[[1.0, 0.1], [0.2, 0.01]], [[0.0, 0.9], [0.8, 0.99]]]),
);
/*
// We can now do some inferences
// First, compute the marginal probabilities of the network without any evidence
net.reset_state();
net.set_evidence(&[]);
println!("===== raw marginal probabilities =====");
for _ in 1..10 {
// this net converges pretty quickly
net.step();
}
let beliefs = net.beliefs();
println!(
" P(Rain) = {:.2}",
beliefs[rain].as_probabilities()[1]
);
println!(
" P(Sprinkler) = {:.2}",
beliefs[sprinkler].as_probabilities()[1]
);
println!(
" P(Wet) = {:.2}",
beliefs[wet].as_probabilities()[1]
);
*/
println!();
println!("===== marginal probabilities assuming the grass is wet =====");
// Now, assuming we see the grass we, what can we infer from this ?
net.reset_state();
net.set_evidence(&[(wet, 1)]);
for i in 1..21 {
// this net is slower to converge
net.step();
let beliefs = net.beliefs();
println!("After iteration {}", i);
println!(
" P(Rain | Wet) = {:.2}",
beliefs[rain].as_probabilities()[1]
);
println!(
" P(Sprinkler | Wet) = {:.2}",
beliefs[sprinkler].as_probabilities()[1]
);
println!(
" P(Wet | Wet) = {:.2}",
beliefs[wet].as_probabilities()[1]
);
}
/*
println!();
println!("===== marginal probabilities assuming the sprinkler is running =====");
// Evidence doesn't need to be at the last node
net.reset_state();
net.set_evidence(&[(sprinkler, 1)]);
for _ in 1..10 {
// this one is quick to converge too
net.step();
}
let beliefs = net.beliefs();
println!(
" P(Rain | Sprinkler) = {:.2}",
beliefs[rain].as_probabilities()[1]
);
println!(
" P(Sprinkler | Sprinkler) = {:.2}",
beliefs[sprinkler].as_probabilities()[1]
);
println!(
" P(Wet | Sprinkler) = {:.2}",
beliefs[wet].as_probabilities()[1]
);
println!();
println!("===== marginal probabilities assuming it's not rainning =====");
// Evidence can even be at the prior !
net.reset_state();
net.set_evidence(&[(rain, 0)]);
for _ in 1..10 {
// this one is quick to converge too
net.step();
}
let beliefs = net.beliefs();
println!(
" P(Rain | not Rain) = {:.2}",
beliefs[rain].as_probabilities()[1]
);
println!(
" P(Sprinkler | not Rain) = {:.2}",
beliefs[sprinkler].as_probabilities()[1]
);
println!(
" P(Wet | not Rain) = {:.2}",
beliefs[wet].as_probabilities()[1]
);
*/
}