Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| import pandas as pd | |
| import time | |
| import plotly.graph_objects as go | |
| st.set_page_config(page_title="Urn Sampling Demo", layout="wide") | |
| st.title("Urn Sampling and Relative Frequencies") | |
| # -------------------------------------------------- | |
| # Controls | |
| # -------------------------------------------------- | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| n0 = st.number_input("Number of 0-balls", 0, 1000, 2) | |
| with col2: | |
| n1 = st.number_input("Number of 1-balls", 0, 1000, 3) | |
| with col3: | |
| n2 = st.number_input("Number of 2-balls", 0, 1000, 5) | |
| draws = st.slider("Number of draws", 10, 5000, 500) | |
| replacement = st.checkbox("Draw with replacement", value=True) | |
| speed = st.slider( | |
| "Animation delay (seconds)", | |
| 0.0, | |
| 0.2, | |
| 0.01, | |
| 0.01 | |
| ) | |
| # -------------------------------------------------- | |
| # Build urn | |
| # -------------------------------------------------- | |
| urn = [0] * n0 + [1] * n1 + [2] * n2 | |
| if len(urn) == 0: | |
| st.warning("Add at least one ball.") | |
| st.stop() | |
| p0 = n0 / len(urn) | |
| p1 = n1 / len(urn) | |
| p2 = n2 / len(urn) | |
| st.markdown( | |
| f""" | |
| **True probabilities** | |
| - P(0) = {p0:.3f} | |
| - P(1) = {p1:.3f} | |
| - P(2) = {p2:.3f} | |
| """ | |
| ) | |
| start = st.button("Start Simulation") | |
| # -------------------------------------------------- | |
| # Simulation | |
| # -------------------------------------------------- | |
| if start: | |
| count0 = 0 | |
| count1 = 0 | |
| count2 = 0 | |
| freq0 = [] | |
| freq1 = [] | |
| freq2 = [] | |
| draw_index = [] | |
| latest_draw_placeholder = st.empty() | |
| stats_placeholder = st.empty() | |
| chart_placeholder = st.empty() | |
| current_urn = urn.copy() | |
| for i in range(1, draws + 1): | |
| if replacement: | |
| draw = np.random.choice(urn) | |
| else: | |
| if len(current_urn) == 0: | |
| break | |
| idx = np.random.randint(len(current_urn)) | |
| draw = current_urn.pop(idx) | |
| if draw == 0: | |
| count0 += 1 | |
| elif draw == 1: | |
| count1 += 1 | |
| else: | |
| count2 += 1 | |
| freq0.append(count0 / i) | |
| freq1.append(count1 / i) | |
| freq2.append(count2 / i) | |
| draw_index.append(i) | |
| latest_draw_placeholder.metric( | |
| "Latest Draw", | |
| int(draw) | |
| ) | |
| stats_placeholder.write( | |
| { | |
| "Count(0)": count0, | |
| "Count(1)": count1, | |
| "Count(2)": count2, | |
| } | |
| ) | |
| fig = go.Figure() | |
| fig.add_trace( | |
| go.Scatter( | |
| x=draw_index, | |
| y=freq0, | |
| mode="lines", | |
| name="Relative freq(0)" | |
| ) | |
| ) | |
| fig.add_trace( | |
| go.Scatter( | |
| x=draw_index, | |
| y=freq1, | |
| mode="lines", | |
| name="Relative freq(1)" | |
| ) | |
| ) | |
| fig.add_trace( | |
| go.Scatter( | |
| x=draw_index, | |
| y=freq2, | |
| mode="lines", | |
| name="Relative freq(2)" | |
| ) | |
| ) | |
| fig.add_hline( | |
| y=p0, | |
| line_dash="dash", | |
| annotation_text="P(0)" | |
| ) | |
| fig.add_hline( | |
| y=p1, | |
| line_dash="dash", | |
| annotation_text="P(1)" | |
| ) | |
| fig.add_hline( | |
| y=p2, | |
| line_dash="dash", | |
| annotation_text="P(2)" | |
| ) | |
| fig.update_layout( | |
| title="Convergence of Relative Frequencies", | |
| xaxis_title="Draw Number", | |
| yaxis_title="Relative Frequency", | |
| yaxis=dict(range=[0, 1]), | |
| height=500 | |
| ) | |
| chart_placeholder.plotly_chart( | |
| fig, | |
| use_container_width=True | |
| ) | |
| if speed > 0: | |
| time.sleep(speed) |