diff --git a/src/multi_swarm/dashboard/pages/02_ga_convergence.py b/src/multi_swarm/dashboard/pages/02_ga_convergence.py new file mode 100644 index 0000000..18a2f3e --- /dev/null +++ b/src/multi_swarm/dashboard/pages/02_ga_convergence.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +import plotly.graph_objects as go +import streamlit as st + +from multi_swarm.dashboard.data import generations_df, get_repo, list_runs_df + +st.title("GA Convergence") + +db_path = st.session_state.get("db_path", "./runs.db") +repo = get_repo(db_path) + +runs = list_runs_df(repo) +if runs.empty: + st.info("Nessuna run.") + st.stop() + +selected = st.selectbox("Run", runs["id"].tolist()) +gens = generations_df(repo, selected) +if gens.empty: + st.warning("Nessuna generazione registrata per questa run.") + st.stop() + +fig = go.Figure() +fig.add_trace( + go.Scatter( + x=gens["generation_idx"], + y=gens["fitness_median"], + name="median", + mode="lines+markers", + ) +) +fig.add_trace( + go.Scatter( + x=gens["generation_idx"], + y=gens["fitness_max"], + name="max", + mode="lines+markers", + ) +) +fig.add_trace( + go.Scatter( + x=gens["generation_idx"], + y=gens["fitness_p90"], + name="p90", + mode="lines+markers", + ) +) +fig.update_layout( + xaxis_title="generation", + yaxis_title="fitness", + title="Fitness convergence", +) +st.plotly_chart(fig, use_container_width=True) + +st.subheader("Entropy") +fig2 = go.Figure() +fig2.add_trace(go.Scatter(x=gens["generation_idx"], y=gens["entropy"], mode="lines+markers")) +fig2.add_hline(y=0.5, line_dash="dash", annotation_text="gate threshold (0.5)") +fig2.update_layout( + xaxis_title="generation", + yaxis_title="entropy", + title="Diversity (fitness entropy)", +) +st.plotly_chart(fig2, use_container_width=True) + +st.subheader("Tabella generazioni") +st.dataframe(gens)