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
//! Porco is a library for working with and composing probability
//! distributions.
//!
//! The API is inspired by the contents of
//! [Probabilistic Functional Programming in Haskell][paper]
//! but with naming conventions that match those of [`Option`] and [`Result`]
//! (such as [`Option::and_then`]).
//!
//! ```rust
//! # use porco::{Probability, Distribution};
//! # #[derive(Debug, PartialEq)]
//! enum Coin {
//!     Heads,
//!     Tails,
//! }
//!
//! impl Coin {
//!     fn flip() -> Distribution<Coin> {
//!         Distribution::uniform(vec![Coin::Heads, Coin::Tails])
//!     }
//! }
//!
//! let coin = Coin::flip();
//! assert_eq!(coin.pmf(&Coin::Heads), Probability(0.5));
//! ```
//!
//! You can compose various operations over `Distribution`s using combinators
//! like [`Distribution::map`], [`Distribution::and_then`], and
//! [`Distribution::given`].
//!
//! ```rust
//! # use porco::{Probability, Distribution};
//! # #[derive(Debug, PartialEq)]
//! # enum Coin {
//! #     Heads,
//! #     Tails,
//! # }
//! # impl Coin {
//! #     fn flip() -> Distribution<Coin> {
//! #         Distribution::uniform(vec![Coin::Heads, Coin::Tails])
//! #     }
//! # }
//! fn reflip_if_tails(coin: Coin) -> Distribution<Coin> {
//!     match coin {
//!         Coin::Heads => Distribution::always(Coin::Heads),
//!         Coin::Tails => Coin::flip(),
//!     }
//! }
//!
//! let coin = Coin::flip().and_then(reflip_if_tails);
//! assert_eq!(coin.pmf(&Coin::Heads), Probability(0.75));
//! ```
//!
//! You can also manipulate random variables and compute summary statistics.
//!
//! ```rust
//! # use porco::{Probability, Distribution};
//! let die = Distribution::uniform(vec![1, 2, 3, 4, 5, 6]);
//! let ev = die.given(|&v| v <= 4).expectation();
//! assert_eq!(ev, 2.5);
//!
//! fn two_sided_die() -> Distribution<u8> {
//!     Distribution::uniform(vec![1, 2])
//! }
//!
//! let x = two_sided_die();
//! let y = two_sided_die();
//! let sum = x.convolve(y);
//! assert_eq!(sum.pmf(&2), Probability(0.25));
//! assert_eq!(sum.pmf(&3), Probability(0.5));
//! ```
//!
//! [paper]: https://web.engr.oregonstate.edu/~erwig/papers/PFP_JFP06.pdf
mod dist;
mod prob;

pub use dist::Distribution;
pub use prob::Probability;