import%20marimo%0A%0A__generated_with%20%3D%20%220.19.8%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20from%20matplotlib.animation%20import%20FuncAnimation%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20from%20matplotlib%20import%20rcParams%0A%20%20%20%20rcParams%5B'text.usetex'%5D%20%3D%20True%0A%20%20%20%20rcParams%5B%22text.latex.preamble%22%5D%20%3D%20r%22%5Cusepackage%7Bamsmath%7D%5Cusepackage%7Bamsfonts%7D%22%0A%20%20%20%20return%20matplotlib%2C%20mo%2C%20np%2C%20plt%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Roots%20of%20Perturbed%20Quadratic%20Equations%0A%0A%20%20%20%20Visualization%20of%20the%20roots%20of%20%24x%5E2%20%2B%20bx%20%2B%20c%20%3D%200%24%20where%20%24b%2C%20c%20%5Cin%20%5Cmathbb%7BC%7D%24%0A%20%20%20%20are%20subject%20to%20random%20Gaussian%20perturbations%20of%20magnitude%20%24%5Cvarepsilon%24.%0A%0A%20%20%20%20The%20density%20of%20the%20root%20distribution%20reveals%20the%20**sensitivity**%20of%20the%20roots%0A%20%20%20%20to%20small%20changes%20in%20the%20coefficients.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(controls%2C%20mo%2C%20plot_out)%3A%0A%20%20%20%20mo.hstack(%5Bcontrols%2C%20plot_out%5D%2C%20justify%3D%22space-around%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20b_re%20%3D%20mo.ui.slider(-3.0%2C%203.0%2C%20step%3D0.1%2C%20value%3D1.0%2C%20label%3D%22Re(b)%22)%0A%20%20%20%20b_im%20%3D%20mo.ui.slider(-3.0%2C%203.0%2C%20step%3D0.1%2C%20value%3D1.0%2C%20label%3D%22Im(b)%22)%0A%20%20%20%20c_re%20%3D%20mo.ui.slider(-3.0%2C%203.0%2C%20step%3D0.1%2C%20value%3D1.8%2C%20label%3D%22Re(c)%22)%0A%20%20%20%20c_im%20%3D%20mo.ui.slider(-3.0%2C%203.0%2C%20step%3D0.1%2C%20value%3D0.0%2C%20label%3D%22Im(c)%22)%0A%0A%20%20%20%20eps_slider%20%3D%20mo.ui.slider(0.01%2C%201.0%2C%20step%3D0.01%2C%20value%3D0.2%2C%20label%3D%22eps%22)%0A%20%20%20%20n_perturb_slider%20%3D%20mo.ui.slider(1000%2C%2050000%2C%20step%3D1000%2C%20value%3D10000%2C%20label%3D%22n_perturb%22)%0A%0A%20%20%20%20root_selector%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3D%7B%22Root%201%22%3A%20%22root_1%22%2C%20%22Root%202%22%3A%20%22root_2%22%2C%20%22Both%22%3A%20%22both%22%7D%2C%0A%20%20%20%20%20%20%20%20value%3D%22Root%202%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Roots%20to%20display%22%0A%20%20%20%20)%0A%0A%20%20%20%20controls%20%3D%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%20Parameters%22)%2C%0A%20%20%20%20%20%20%20%20b_re%2C%20%0A%20%20%20%20%20%20%20%20b_im%2C%0A%20%20%20%20%20%20%20%20c_re%2C%20%0A%20%20%20%20%20%20%20%20c_im%2C%0A%20%20%20%20%20%20%20%20eps_slider%2C%20%0A%20%20%20%20%20%20%20%20n_perturb_slider%2C%0A%20%20%20%20%20%20%20%20root_selector%5D%2C%20%20justify%3D%22space-around%22%2C%20align%3D%22center%22)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20b_im%2C%0A%20%20%20%20%20%20%20%20b_re%2C%0A%20%20%20%20%20%20%20%20c_im%2C%0A%20%20%20%20%20%20%20%20c_re%2C%0A%20%20%20%20%20%20%20%20controls%2C%0A%20%20%20%20%20%20%20%20eps_slider%2C%0A%20%20%20%20%20%20%20%20n_perturb_slider%2C%0A%20%20%20%20%20%20%20%20root_selector%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(b_im%2C%20b_re%2C%20c_im%2C%20c_re%2C%20eps_slider%2C%20n_perturb_slider%2C%20np%2C%20root_selector)%3A%0A%20%20%20%20eps%20%3D%20eps_slider.value%0A%20%20%20%20n_perturb%20%3D%20n_perturb_slider.value%0A%20%20%20%20b%20%3D%20complex(b_re.value%2C%20b_im.value)%0A%20%20%20%20c%20%3D%20complex(c_re.value%2C%20c_im.value)%0A%0A%20%20%20%20rng%20%3D%20np.random.default_rng(42)%0A%0A%20%20%20%20b_pert%20%3D%20b%20%2B%20rng.normal(0.%2C%20eps%2C%20n_perturb)%20%2B%20rng.normal(0.%2C%20eps%2C%20n_perturb)%20*%201j%0A%20%20%20%20c_pert%20%3D%20c%20%2B%20rng.normal(0.%2C%20eps%2C%20n_perturb)%20%2B%20rng.normal(0.%2C%20eps%2C%20n_perturb)%20*%201j%0A%0A%20%20%20%20discriminant%20%3D%20b_pert**2%20-%204%20*%20c_pert%0A%20%20%20%20root_1%20%3D%200.5%20*%20(-b_pert%20%2B%20np.sqrt(discriminant))%0A%20%20%20%20root_2%20%3D%200.5%20*%20(-b_pert%20-%20np.sqrt(discriminant))%0A%0A%20%20%20%20_sel%20%3D%20root_selector.value%0A%20%20%20%20if%20_sel%20%3D%3D%20%22root_1%22%3A%0A%20%20%20%20%20%20%20%20points%20%3D%20root_1%0A%20%20%20%20elif%20_sel%20%3D%3D%20%22root_2%22%3A%0A%20%20%20%20%20%20%20%20points%20%3D%20root_2%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20points%20%3D%20np.concatenate((root_1%2C%20root_2))%0A%20%20%20%20return%20(points%2C)%0A%0A%0A%40app.cell%0Adef%20_(b_im%2C%20b_re%2C%20c_im%2C%20c_re%2C%20matplotlib%2C%20np%2C%20plt%2C%20points)%3A%0A%20%20%20%20dx%20%3D%20%5B-5.%2C%205.%5D%0A%20%20%20%20dy%20%3D%20%5B-5.%2C%205.%5D%0A%20%20%20%20bg_color%20%3D%20%22k%22%0A%0A%20%20%20%20cmap%20%3D%20matplotlib.colormaps%5B%22Wistia%22%5D%0A%20%20%20%20text_color%20%3D%20%22w%22%23cmap(0.4)%0A%0A%20%20%20%20b_str%20%3D%20f%22%7Bb_re.value%3A%2B.1f%7D%7Bb_im.value%3A%2B.1f%7Di%22%0A%20%20%20%20c_str%20%3D%20f%22%7Bc_re.value%3A%2B.1f%7D%7Bc_im.value%3A%2B.1f%7Di%22%0A%0A%20%20%20%20fig%2C%20ax%20%3D%20plt.subplots(figsize%3D(6%2C%206))%0A%20%20%20%20fig.set_facecolor(bg_color)%0A%20%20%20%20ax.set_facecolor(bg_color)%0A%0A%20%20%20%20prob%2C%20_%2C%20_%20%3D%20np.histogram2d(%0A%20%20%20%20%20%20%20%20np.real(points)%2C%20np.imag(points)%2C%0A%20%20%20%20%20%20%20%20bins%3D400%2C%20range%3D%5Bdx%2C%20dy%5D%2C%20density%3DTrue%0A%20%20%20%20)%0A%0A%20%20%20%20ax.scatter(%0A%20%20%20%20%20%20%20%20np.real(points)%2C%20np.imag(points)%2C%0A%20%20%20%20%20%20%20%20alpha%3D0.6%2C%20c%3D%22y%22%2C%20s%3D0.5%2C%20linewidths%3D0.0%2C%20zorder%3D0%0A%20%20%20%20)%0A%0A%20%20%20%20ax.imshow(%0A%20%20%20%20%20%20%20%20np.log(1%20%2B%20prob.T)%2C%20origin%3D%22lower%22%2C%0A%20%20%20%20%20%20%20%20extent%3Ddx%20%2B%20dy%2C%0A%20%20%20%20%20%20%20%20zorder%3D-10%2C%20cmap%3D%22CMRmap%22%2C%0A%20%20%20%20%20%20%20%20interpolation%3D%22bicubic%22%2C%20vmin%3D0%2C%20vmax%3D0.5%0A%20%20%20%20)%0A%0A%20%20%20%20ax.set_aspect('equal'%2C%20'box')%0A%20%20%20%20ax.set_xlim(dx)%0A%20%20%20%20ax.set_ylim(dy)%0A%0A%20%20%20%20ax.set_title(r%22%24x%5E2%20%25s%20x%20%25s%3D0%24%22%25(b_str%2C%20c_str)%2C%20color%3Dtext_color)%0A%0A%20%20%20%20ax.tick_params(colors%3D'white')%0A%20%20%20%20for%20spine%20in%20ax.spines.values()%3A%0A%20%20%20%20%20%20%20%20spine.set_color('white')%0A%20%20%20%20ax.set_xlabel(r%22%24%5Cmathrm%7BRe%7D(x)%24%22%2C%20fontsize%3D14%2C%20color%3Dtext_color)%0A%20%20%20%20ax.set_ylabel(r%22%24%5Cmathrm%7BIm%7D(x)%24%22%2C%20fontsize%3D14%2C%20color%3Dtext_color)%0A%0A%20%20%20%20fig.text(0.72%2C%200.05%2C%20r%22%5Ctextrm%7BSimone%20Conradi%2C%202026%7D%22%2C%20fontsize%3D10%2C%20c%3Dtext_color)%0A%0A%20%20%20%20%23plt.tight_layout()%0A%20%20%20%20plot_out%20%3D%20plt.gca()%0A%20%20%20%20return%20(plot_out%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
504ef367ec3d0eeadc52da2396897104