|
| 1 | +# /// script |
| 2 | +# requires-python = ">=3.10" |
| 3 | +# dependencies = [ |
| 4 | +# "marimo", |
| 5 | +# "matplotlib", |
| 6 | +# "matplotlib-venn" |
| 7 | +# ] |
| 8 | +# /// |
| 9 | + |
| 10 | +import marimo |
| 11 | + |
| 12 | +__generated_with = "0.11.2" |
| 13 | +app = marimo.App() |
| 14 | + |
| 15 | + |
| 16 | +@app.cell |
| 17 | +def _(): |
| 18 | + import marimo as mo |
| 19 | + return (mo,) |
| 20 | + |
| 21 | + |
| 22 | +@app.cell |
| 23 | +def _(): |
| 24 | + import matplotlib.pyplot as plt |
| 25 | + from matplotlib_venn import venn2 |
| 26 | + import numpy as np |
| 27 | + return np, plt, venn2 |
| 28 | + |
| 29 | + |
| 30 | +@app.cell(hide_code=True) |
| 31 | +def _(mo): |
| 32 | + mo.md( |
| 33 | + r""" |
| 34 | + # Probability of Or |
| 35 | +
|
| 36 | + When calculating the probability of either one event _or_ another occurring, we need to be careful about how we combine probabilities. The method depends on whether the events can happen together[<sup>1</sup>](https://chrispiech.github.io/probabilityForComputerScientists/en/part1/prob_or/). |
| 37 | +
|
| 38 | + Let's explore how to calculate $P(E \cup F)$ or $P(E \text{ or } F)$ in different scenarios. |
| 39 | + """ |
| 40 | + ) |
| 41 | + return |
| 42 | + |
| 43 | + |
| 44 | +@app.cell(hide_code=True) |
| 45 | +def _(mo): |
| 46 | + mo.md( |
| 47 | + r""" |
| 48 | + ## Mutually Exclusive Events |
| 49 | +
|
| 50 | + Two events $E$ and $F$ are **mutually exclusive** if they cannot occur simultaneously. |
| 51 | + In set notation, this means: |
| 52 | +
|
| 53 | + $E \cap F = \emptyset$ |
| 54 | +
|
| 55 | + For example: |
| 56 | +
|
| 57 | + - Rolling an even number (2,4,6) vs rolling an odd number (1,3,5) |
| 58 | + - Drawing a heart vs drawing a spade from a deck |
| 59 | + - Passing vs failing a test |
| 60 | +
|
| 61 | + Here's a Python function to check if two sets of outcomes are mutually exclusive: |
| 62 | + """ |
| 63 | + ) |
| 64 | + return |
| 65 | + |
| 66 | + |
| 67 | +@app.cell |
| 68 | +def _(): |
| 69 | + def are_mutually_exclusive(event1, event2): |
| 70 | + return len(event1.intersection(event2)) == 0 |
| 71 | + |
| 72 | + # Example with dice rolls |
| 73 | + even_numbers = {2, 4, 6} |
| 74 | + odd_numbers = {1, 3, 5} |
| 75 | + prime_numbers = {2, 3, 5, 7} |
| 76 | + return are_mutually_exclusive, even_numbers, odd_numbers, prime_numbers |
| 77 | + |
| 78 | + |
| 79 | +@app.cell |
| 80 | +def _(are_mutually_exclusive, even_numbers, odd_numbers): |
| 81 | + are_mutually_exclusive(even_numbers, odd_numbers) |
| 82 | + return |
| 83 | + |
| 84 | + |
| 85 | +@app.cell |
| 86 | +def _(are_mutually_exclusive, even_numbers, prime_numbers): |
| 87 | + are_mutually_exclusive(even_numbers, prime_numbers) |
| 88 | + return |
| 89 | + |
| 90 | + |
| 91 | +@app.cell(hide_code=True) |
| 92 | +def _(mo): |
| 93 | + mo.md( |
| 94 | + r""" |
| 95 | + ## Or with Mutually Exclusive Events |
| 96 | +
|
| 97 | + For mutually exclusive events, the probability of either event occurring is simply the sum of their individual probabilities: |
| 98 | +
|
| 99 | + $P(E \cup F) = P(E) + P(F)$ |
| 100 | +
|
| 101 | + This extends to multiple events. For $n$ mutually exclusive events $E_1, E_2, \ldots, E_n$: |
| 102 | +
|
| 103 | + $P(E_1 \cup E_2 \cup \cdots \cup E_n) = \sum_{i=1}^n P(E_i)$ |
| 104 | +
|
| 105 | + Let's implement this calculation: |
| 106 | + """ |
| 107 | + ) |
| 108 | + return |
| 109 | + |
| 110 | + |
| 111 | +@app.cell |
| 112 | +def _(): |
| 113 | + def prob_union_mutually_exclusive(probabilities): |
| 114 | + return sum(probabilities) |
| 115 | + |
| 116 | + # Example: Rolling a die |
| 117 | + # P(even) = P(2) + P(4) + P(6) |
| 118 | + p_even_mutually_exclusive = prob_union_mutually_exclusive([1/6, 1/6, 1/6]) |
| 119 | + print(f"P(rolling an even number) = {p_even_mutually_exclusive}") |
| 120 | + |
| 121 | + # P(prime) = P(2) + P(3) + P(5) |
| 122 | + p_prime_mutually_exclusive = prob_union_mutually_exclusive([1/6, 1/6, 1/6]) |
| 123 | + print(f"P(rolling a prime number) = {p_prime_mutually_exclusive}") |
| 124 | + return ( |
| 125 | + p_even_mutually_exclusive, |
| 126 | + p_prime_mutually_exclusive, |
| 127 | + prob_union_mutually_exclusive, |
| 128 | + ) |
| 129 | + |
| 130 | + |
| 131 | +@app.cell(hide_code=True) |
| 132 | +def _(mo): |
| 133 | + mo.md( |
| 134 | + r""" |
| 135 | + ## Or with Non-Mutually Exclusive Events |
| 136 | +
|
| 137 | + When events can occur together, we need to use the **inclusion-exclusion principle**: |
| 138 | +
|
| 139 | + $P(E \cup F) = P(E) + P(F) - P(E \cap F)$ |
| 140 | +
|
| 141 | + Why subtract $P(E \cap F)$? Because when we add $P(E)$ and $P(F)$, we count the overlap twice! |
| 142 | +
|
| 143 | + For example, consider calculating $P(\text{prime or even})$ when rolling a die: |
| 144 | + - Prime numbers: {2, 3, 5} |
| 145 | + - Even numbers: {2, 4, 6} |
| 146 | + - The number 2 is counted twice unless we subtract its probability |
| 147 | +
|
| 148 | + Here's how to implement this calculation: |
| 149 | + """ |
| 150 | + ) |
| 151 | + return |
| 152 | + |
| 153 | + |
| 154 | +@app.cell |
| 155 | +def _(): |
| 156 | + def prob_union_general(p_a, p_b, p_intersection): |
| 157 | + """Calculate probability of union for any two events""" |
| 158 | + return p_a + p_b - p_intersection |
| 159 | + |
| 160 | + # Example: Rolling a die |
| 161 | + # P(prime or even) |
| 162 | + p_prime_general = 3/6 # P(prime) = P(2,3,5) |
| 163 | + p_even_general = 3/6 # P(even) = P(2,4,6) |
| 164 | + p_intersection = 1/6 # P(intersection) = P(2) |
| 165 | + |
| 166 | + result = prob_union_general(p_prime_general, p_even_general, p_intersection) |
| 167 | + print(f"P(prime or even) = {p_prime_general} + {p_even_general} - {p_intersection} = {result}") |
| 168 | + return ( |
| 169 | + p_even_general, |
| 170 | + p_intersection, |
| 171 | + p_prime_general, |
| 172 | + prob_union_general, |
| 173 | + result, |
| 174 | + ) |
| 175 | + |
| 176 | + |
| 177 | +@app.cell(hide_code=True) |
| 178 | +def _(mo): |
| 179 | + mo.md( |
| 180 | + r""" |
| 181 | + ### Extension to Three Events |
| 182 | +
|
| 183 | + For three events, the inclusion-exclusion principle becomes: |
| 184 | +
|
| 185 | + $P(E_1 \cup E_2 \cup E_3) = P(E_1) + P(E_2) + P(E_3)$ |
| 186 | + $- P(E_1 \cap E_2) - P(E_1 \cap E_3) - P(E_2 \cap E_3)$ |
| 187 | + $+ P(E_1 \cap E_2 \cap E_3)$ |
| 188 | +
|
| 189 | + The pattern is: |
| 190 | +
|
| 191 | + 1. Add individual probabilities |
| 192 | + 2. Subtract probabilities of pairs |
| 193 | + 3. Add probability of triple intersection |
| 194 | + """ |
| 195 | + ) |
| 196 | + return |
| 197 | + |
| 198 | + |
| 199 | +@app.cell(hide_code=True) |
| 200 | +def _(mo): |
| 201 | + mo.md(r"""### Interactive example:""") |
| 202 | + return |
| 203 | + |
| 204 | + |
| 205 | +@app.cell |
| 206 | +def _(event_type): |
| 207 | + event_type |
| 208 | + return |
| 209 | + |
| 210 | + |
| 211 | +@app.cell(hide_code=True) |
| 212 | +def _(mo): |
| 213 | + # Create a dropdown to select the type of events to visualize |
| 214 | + event_type = mo.ui.dropdown( |
| 215 | + options=[ |
| 216 | + "Mutually Exclusive Events (Rolling Odd vs Even)", |
| 217 | + "Non-Mutually Exclusive Events (Prime vs Even)", |
| 218 | + "Three Events (Less than 3, Even, Prime)" |
| 219 | + ], |
| 220 | + value="Mutually Exclusive Events (Rolling Odd vs Even)", |
| 221 | + label="Select Event Type" |
| 222 | + ) |
| 223 | + return (event_type,) |
| 224 | + |
| 225 | + |
| 226 | +@app.cell(hide_code=True) |
| 227 | +def _(event_type, mo, plt, venn2): |
| 228 | + # Define the events and their probabilities |
| 229 | + events_data = { |
| 230 | + "Mutually Exclusive Events (Rolling Odd vs Even)": { |
| 231 | + "sets": (round(3/6, 2), round(3/6, 2), 0), # (odd, even, intersection) |
| 232 | + "labels": ("Odd\n{1,3,5}", "Even\n{2,4,6}"), |
| 233 | + "title": "Mutually Exclusive Events: Odd vs Even Numbers", |
| 234 | + "explanation": r""" |
| 235 | + ### Mutually Exclusive Events |
| 236 | +
|
| 237 | + $P(\text{Odd}) = \frac{3}{6} = 0.5$ |
| 238 | + $P(\text{Even}) = \frac{3}{6} = 0.5$ |
| 239 | + $P(\text{Odd} \cap \text{Even}) = 0$ |
| 240 | +
|
| 241 | + $P(\text{Odd} \cup \text{Even}) = P(\text{Odd}) + P(\text{Even}) = 1$ |
| 242 | +
|
| 243 | + These events are mutually exclusive because a number cannot be both odd and even. |
| 244 | + """ |
| 245 | + }, |
| 246 | + "Non-Mutually Exclusive Events (Prime vs Even)": { |
| 247 | + "sets": (round(2/6, 2), round(2/6, 2), round(1/6, 2)), # (prime-only, even-only, intersection) |
| 248 | + "labels": ("Prime\n{3,5}", "Even\n{4,6}"), |
| 249 | + "title": "Non-Mutually Exclusive: Prime vs Even Numbers", |
| 250 | + "explanation": r""" |
| 251 | + ### Non-Mutually Exclusive Events |
| 252 | +
|
| 253 | + $P(\text{Prime}) = \frac{3}{6} = 0.5$ (2,3,5) |
| 254 | + $P(\text{Even}) = \frac{3}{6} = 0.5$ (2,4,6) |
| 255 | + $P(\text{Prime} \cap \text{Even}) = \frac{1}{6}$ (2) |
| 256 | +
|
| 257 | + $P(\text{Prime} \cup \text{Even}) = \frac{3}{6} + \frac{3}{6} - \frac{1}{6} = \frac{5}{6}$ |
| 258 | +
|
| 259 | + These events overlap because 2 is both prime and even. |
| 260 | + """ |
| 261 | + }, |
| 262 | + "Three Events (Less than 3, Even, Prime)": { |
| 263 | + "sets": (round(1/6, 2), round(2/6, 2), round(1/6, 2)), # (less than 3, even, intersection) |
| 264 | + "labels": ("<3\n{1,2}", "Even\n{2,4,6}"), |
| 265 | + "title": "Complex Example: Numbers < 3 and Even Numbers", |
| 266 | + "explanation": r""" |
| 267 | + ### Complex Event Interaction |
| 268 | +
|
| 269 | + $P(x < 3) = \frac{2}{6}$ (1,2) |
| 270 | + $P(\text{Even}) = \frac{3}{6}$ (2,4,6) |
| 271 | + $P(x < 3 \cap \text{Even}) = \frac{1}{6}$ (2) |
| 272 | +
|
| 273 | + $P(x < 3 \cup \text{Even}) = \frac{2}{6} + \frac{3}{6} - \frac{1}{6} = \frac{4}{6}$ |
| 274 | +
|
| 275 | + The number 2 belongs to both sets, requiring the inclusion-exclusion principle. |
| 276 | + """ |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + # Get data for selected event type |
| 281 | + data = events_data[event_type.value] |
| 282 | + |
| 283 | + # Create visualization |
| 284 | + plt.figure(figsize=(10, 5)) |
| 285 | + v = venn2(subsets=data["sets"], |
| 286 | + set_labels=data["labels"]) |
| 287 | + plt.title(data["title"]) |
| 288 | + |
| 289 | + # Display explanation alongside visualization |
| 290 | + mo.hstack([ |
| 291 | + plt.gcf(), |
| 292 | + mo.md(data["explanation"]) |
| 293 | + ]) |
| 294 | + return data, events_data, v |
| 295 | + |
| 296 | + |
| 297 | +@app.cell(hide_code=True) |
| 298 | +def _(mo): |
| 299 | + mo.md( |
| 300 | + r""" |
| 301 | + ## 🤔 Test Your Understanding |
| 302 | +
|
| 303 | + Consider rolling a six-sided die. Which of these statements are true? |
| 304 | +
|
| 305 | + <details> |
| 306 | + <summary>1. P(even or less than 3) = P(even) + P(less than 3)</summary> |
| 307 | +
|
| 308 | + ❌ Incorrect! These events are not mutually exclusive (2 is both even and less than 3). |
| 309 | + We need to use the inclusion-exclusion principle. |
| 310 | + </details> |
| 311 | +
|
| 312 | + <details> |
| 313 | + <summary>2. P(even or greater than 4) = 4/6</summary> |
| 314 | +
|
| 315 | + ✅ Correct! {2,4,6} ∪ {5,6} = {2,4,5,6}, so probability is 4/6. |
| 316 | + </details> |
| 317 | +
|
| 318 | + <details> |
| 319 | + <summary>3. P(prime or odd) = 5/6</summary> |
| 320 | +
|
| 321 | + ✅ Correct! {2,3,5} ∪ {1,3,5} = {1,2,3,5}, so probability is 5/6. |
| 322 | + </details> |
| 323 | + """ |
| 324 | + ) |
| 325 | + return |
| 326 | + |
| 327 | + |
| 328 | +@app.cell(hide_code=True) |
| 329 | +def _(mo): |
| 330 | + mo.md( |
| 331 | + """ |
| 332 | + ## Summary |
| 333 | +
|
| 334 | + You've learned: |
| 335 | +
|
| 336 | + - How to identify mutually exclusive events |
| 337 | + - The addition rule for mutually exclusive events |
| 338 | + - The inclusion-exclusion principle for overlapping events |
| 339 | + - How to extend these concepts to multiple events |
| 340 | +
|
| 341 | + In the next lesson, we'll explore **conditional probability** - how the probability |
| 342 | + of one event changes when we know another event has occurred. |
| 343 | + """ |
| 344 | + ) |
| 345 | + return |
| 346 | + |
| 347 | + |
| 348 | +if __name__ == "__main__": |
| 349 | + app.run() |
0 commit comments