Spaces:
Sleeping
Sleeping
Merge pull request #31 from marimo-team/haleshot-02_axioms
Browse files- probability/02_axioms.py +214 -0
probability/02_axioms.py
ADDED
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# /// script
|
2 |
+
# requires-python = ">=3.11"
|
3 |
+
# dependencies = [
|
4 |
+
# "marimo",
|
5 |
+
# "matplotlib==3.10.0",
|
6 |
+
# "numpy==2.2.2",
|
7 |
+
# ]
|
8 |
+
# ///
|
9 |
+
|
10 |
+
import marimo
|
11 |
+
|
12 |
+
__generated_with = "0.11.2"
|
13 |
+
app = marimo.App(width="medium")
|
14 |
+
|
15 |
+
|
16 |
+
@app.cell
|
17 |
+
def _():
|
18 |
+
import marimo as mo
|
19 |
+
return (mo,)
|
20 |
+
|
21 |
+
|
22 |
+
@app.cell(hide_code=True)
|
23 |
+
def _(mo):
|
24 |
+
mo.md(
|
25 |
+
r"""
|
26 |
+
# Axioms of Probability
|
27 |
+
|
28 |
+
Probability theory is built on three fundamental axioms, known as the [Kolmogorov axioms](https://en.wikipedia.org/wiki/Probability_axioms). These axioms form
|
29 |
+
the mathematical foundation for all of probability theory[<sup>1</sup>](https://chrispiech.github.io/probabilityForComputerScientists/en/part1/probability).
|
30 |
+
|
31 |
+
Let's explore each axiom and understand why they make intuitive sense:
|
32 |
+
"""
|
33 |
+
)
|
34 |
+
return
|
35 |
+
|
36 |
+
|
37 |
+
@app.cell(hide_code=True)
|
38 |
+
def _(mo):
|
39 |
+
mo.md(
|
40 |
+
r"""
|
41 |
+
## The Three Axioms
|
42 |
+
|
43 |
+
| Axiom | Mathematical Form | Meaning |
|
44 |
+
|-------|------------------|----------|
|
45 |
+
| **Axiom 1** | $0 \leq P(E) \leq 1$ | All probabilities are between 0 and 1 |
|
46 |
+
| **Axiom 2** | $P(S) = 1$ | The probability of the sample space is 1 |
|
47 |
+
| **Axiom 3** | $P(E \cup F) = P(E) + P(F)$ | For mutually exclusive events, probabilities add |
|
48 |
+
|
49 |
+
where the set $S$ is the sample space (all possible outcomes), and $E$ and $F$ are sets that represent events. The notation $P(E)$ denotes the probability of $E$, which you can interpret as the chance that something happens. $P(E) = 0$ means that the event cannot happen, while $P(E) = 1$ means the event will happen no matter what; $P(E) = 0.5$ means that $E$ has a 50% chance of happening.
|
50 |
+
|
51 |
+
For an example, when rolling a fair six-sided die once, the sample space $S$ is the set of die faces ${1, 2, 3, 4, 5, 6}$, and there are many possible events; we'll see some examples below.
|
52 |
+
"""
|
53 |
+
)
|
54 |
+
return
|
55 |
+
|
56 |
+
|
57 |
+
@app.cell(hide_code=True)
|
58 |
+
def _(mo):
|
59 |
+
mo.md(
|
60 |
+
r"""
|
61 |
+
## Understanding Through Examples
|
62 |
+
|
63 |
+
Let's explore these axioms using a simple experiment: rolling a fair six-sided die.
|
64 |
+
We'll use this to demonstrate why each axiom makes intuitive sense.
|
65 |
+
"""
|
66 |
+
)
|
67 |
+
return
|
68 |
+
|
69 |
+
|
70 |
+
@app.cell
|
71 |
+
def _(event):
|
72 |
+
event
|
73 |
+
return
|
74 |
+
|
75 |
+
|
76 |
+
@app.cell(hide_code=True)
|
77 |
+
def _(mo):
|
78 |
+
# Create an interactive widget to explore different events
|
79 |
+
|
80 |
+
event = mo.ui.dropdown(
|
81 |
+
|
82 |
+
options=[
|
83 |
+
|
84 |
+
"Rolling an even number (2,4,6)",
|
85 |
+
|
86 |
+
"Rolling an odd number (1,3,5)",
|
87 |
+
|
88 |
+
"Rolling a prime number (2,3,5)",
|
89 |
+
|
90 |
+
"Rolling less than 4 (1,2,3)",
|
91 |
+
|
92 |
+
"Any possible roll (1,2,3,4,5,6)",
|
93 |
+
|
94 |
+
],
|
95 |
+
|
96 |
+
value="Rolling an even number (2,4,6)",
|
97 |
+
|
98 |
+
label="Select an event"
|
99 |
+
|
100 |
+
)
|
101 |
+
return (event,)
|
102 |
+
|
103 |
+
|
104 |
+
@app.cell(hide_code=True)
|
105 |
+
def _(event, mo, np, plt):
|
106 |
+
# Define the probabilities for each event
|
107 |
+
event_map = {
|
108 |
+
"Rolling an even number (2,4,6)": [2, 4, 6],
|
109 |
+
"Rolling an odd number (1,3,5)": [1, 3, 5],
|
110 |
+
"Rolling a prime number (2,3,5)": [2, 3, 5],
|
111 |
+
"Rolling less than 4 (1,2,3)": [1, 2, 3],
|
112 |
+
"Any possible roll (1,2,3,4,5,6)": [1, 2, 3, 4, 5, 6],
|
113 |
+
}
|
114 |
+
|
115 |
+
# Get outcomes directly from the event value
|
116 |
+
outcomes = event_map[event.value]
|
117 |
+
prob = len(outcomes) / 6
|
118 |
+
|
119 |
+
# Visualize the probability
|
120 |
+
dice = np.arange(1, 7)
|
121 |
+
colors = ['#1f77b4' if d in outcomes else '#d3d3d3' for d in dice]
|
122 |
+
|
123 |
+
fig, ax = plt.subplots(figsize=(8, 2))
|
124 |
+
ax.bar(dice, np.ones_like(dice), color=colors)
|
125 |
+
ax.set_xticks(dice)
|
126 |
+
ax.set_yticks([])
|
127 |
+
ax.set_title(f"P(Event) = {prob:.2f}")
|
128 |
+
|
129 |
+
# Add explanation
|
130 |
+
explanation = mo.md(f"""
|
131 |
+
**Event**: {event.value}
|
132 |
+
|
133 |
+
**Probability**: {prob:.2f}
|
134 |
+
|
135 |
+
**Favorable outcomes**: {outcomes}
|
136 |
+
|
137 |
+
This example demonstrates:
|
138 |
+
|
139 |
+
- Axiom 1: The probability is between 0 and 1
|
140 |
+
|
141 |
+
- Axiom 2: For the sample space, P(S) = 1
|
142 |
+
|
143 |
+
- Axiom 3: The probability is the sum of individual outcome probabilities
|
144 |
+
""")
|
145 |
+
|
146 |
+
mo.hstack([plt.gcf(), explanation])
|
147 |
+
return ax, colors, dice, event_map, explanation, fig, outcomes, prob
|
148 |
+
|
149 |
+
|
150 |
+
@app.cell(hide_code=True)
|
151 |
+
def _(mo):
|
152 |
+
mo.md(
|
153 |
+
r"""
|
154 |
+
## Why These Axioms Matter
|
155 |
+
|
156 |
+
These axioms are more than just rules - they provide the foundation for all of probability theory:
|
157 |
+
|
158 |
+
1. **Non-negativity** (Axiom 1) makes intuitive sense: you can't have a negative number of occurrences
|
159 |
+
in any experiment.
|
160 |
+
|
161 |
+
2. **Normalization** (Axiom 2) ensures that something must happen - the total probability must be 1.
|
162 |
+
|
163 |
+
3. **Additivity** (Axiom 3) lets us build complex probabilities from simple ones, but only for events
|
164 |
+
that can't happen together (mutually exclusive events).
|
165 |
+
|
166 |
+
From these simple rules, we can derive all the powerful tools of probability theory that are used in
|
167 |
+
statistics, machine learning, and other fields.
|
168 |
+
"""
|
169 |
+
)
|
170 |
+
return
|
171 |
+
|
172 |
+
|
173 |
+
@app.cell(hide_code=True)
|
174 |
+
def _(mo):
|
175 |
+
mo.md(
|
176 |
+
r"""
|
177 |
+
## 🤔 Test Your Understanding
|
178 |
+
|
179 |
+
Consider rolling two dice. Which of these statements follow from the axioms?
|
180 |
+
|
181 |
+
<details>
|
182 |
+
<summary>1. P(sum is 13) = 0</summary>
|
183 |
+
|
184 |
+
✅ Correct! This follows from Axiom 1. Since no combination of dice can sum to 13,
|
185 |
+
the probability must be non-negative but can be 0.
|
186 |
+
</details>
|
187 |
+
|
188 |
+
<details>
|
189 |
+
<summary>2. P(sum is 7) + P(sum is not 7) = 1</summary>
|
190 |
+
|
191 |
+
✅ Correct! This follows from Axioms 2 and 3. These events are mutually exclusive and cover
|
192 |
+
the entire sample space.
|
193 |
+
</details>
|
194 |
+
|
195 |
+
<details>
|
196 |
+
<summary>3. P(first die is 6 or second die is 6) = P(first die is 6) + P(second die is 6)</summary>
|
197 |
+
|
198 |
+
❌ Incorrect! This doesn't follow from Axiom 3 because the events are not mutually exclusive -
|
199 |
+
you could roll (6,6).
|
200 |
+
</details>
|
201 |
+
"""
|
202 |
+
)
|
203 |
+
return
|
204 |
+
|
205 |
+
|
206 |
+
@app.cell
|
207 |
+
def _():
|
208 |
+
import numpy as np
|
209 |
+
import matplotlib.pyplot as plt
|
210 |
+
return np, plt
|
211 |
+
|
212 |
+
|
213 |
+
if __name__ == "__main__":
|
214 |
+
app.run()
|