%22%22%22Generate%20scaling%20figures%20and%20table%20benchmarks%20for%20minvar_paper.tex.%22%22%22%0A%0A%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22matplotlib%22%2C%0A%23%20%20%20%20%20%22numpy%22%2C%0A%23%20%20%20%20%20%22pandas%22%2C%0A%23%20%20%20%20%20%22pyarrow%22%2C%0A%23%20%20%20%20%20%22fast-minimum-variance%22%2C%0A%23%20%20%20%20%20%22marimo%22%0A%23%20%5D%0A%23%20%5Btool.uv.sources%5D%0A%23%20fast-minimum-variance%20%3D%20%7B%20path%20%3D%20%22..%2F..%2F..%22%2C%20editable%20%3D%20true%20%7D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.5%22%0Aapp%20%3D%20marimo.App()%0A%0Awith%20app.setup%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20matplotlib%20as%20mpl%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20from%20_common%20import%20print_table%2C%20run_timed%2C%20set_notebook_plot_style%0A%0A%20%20%20%20from%20fast_minimum_variance.minvar_problem%20import%20_MinVarProblem%20as%20MinVarProblem%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20set_notebook_plot_style(mpl)%0A%0A%20%20%20%20%23%20%E2%94%80%E2%94%80%20Table%202%3A%20S%26P%20500%20%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%0A%0A%20%20%20%20print()%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%20%20%20%20print(%22S%26P%20500%20%20n%3D495%2C%20T%3D1192%20%20(long-only%20minimum%20variance)%22)%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%20%20%20%20file%20%3D%20Path(__file__).parent%20%2F%20%22data%22%20%2F%20%22sp500_pct_returns.parquet%22%0A%20%20%20%20df%20%3D%20pd.read_parquet(file)%0A%20%20%20%20R_sp%20%3D%20df.to_numpy()%0A%20%20%20%20T_sp%2C%20N_sp%20%3D%20R_sp.shape%0A%20%20%20%20alpha_sp%20%3D%200.5%0A%20%20%20%20target_sp%20%3D%20np.var(R_sp)%20*%20np.eye(N_sp)%20%20%23%20mean%20squared%20entry%20%3D%20bar_lambda%0A%20%20%20%20print(f%22Date%20range%3A%20%7Bdf.index%5B0%5D.date()%7D%20%E2%86%92%20%7Bdf.index%5B-1%5D.date()%7D%22)%0A%20%20%20%20print(f%22alpha%20%3D%20%7Balpha_sp%3A.4f%7D%22)%0A%0A%20%20%20%20configs_sp_no_lw%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22cvxpy%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_cvxpy())%2C%0A%20%20%20%20%20%20%20%20(%22clarabel%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_clarabel())%2C%0A%20%20%20%20%20%20%20%20(%22osqp%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_osqp())%2C%0A%20%20%20%20%20%20%20%20(%22kkt%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_kkt())%2C%0A%20%20%20%20%20%20%20%20(%22cg%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_cg())%2C%0A%20%20%20%20%20%20%20%20(%22nnls%22%2C%20lambda%3A%20MinVarProblem(R_sp).solve_nnls())%2C%0A%20%20%20%20%5D%0A%20%20%20%20configs_sp_lw%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22cvxpy%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_cvxpy())%2C%0A%20%20%20%20%20%20%20%20(%22clarabel%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_clarabel())%2C%0A%20%20%20%20%20%20%20%20(%22osqp%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_osqp())%2C%0A%20%20%20%20%20%20%20%20(%22kkt%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_kkt())%2C%0A%20%20%20%20%20%20%20%20(%22cg%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_cg())%2C%0A%20%20%20%20%20%20%20%20(%22nnls%22%2C%20lambda%3A%20MinVarProblem(R_sp%2C%20alpha%3Dalpha_sp%2C%20target%3Dtarget_sp).solve_nnls())%2C%0A%20%20%20%20%5D%0A%0A%20%20%20%20sp_no_lw%2C%20sp_lw%20%3D%20%7B%7D%2C%20%7B%7D%0A%20%20%20%20for%20key%2C%20fn%20in%20configs_sp_no_lw%3A%0A%20%20%20%20%20%20%20%20(w%2C%20iters)%2C%20t%20%3D%20run_timed(fn)%0A%20%20%20%20%20%20%20%20sp_no_lw%5Bkey%5D%20%3D%20%7B%22time_s%22%3A%20t%2C%20%22iters%22%3A%20iters%7D%0A%20%20%20%20for%20key%2C%20fn%20in%20configs_sp_lw%3A%0A%20%20%20%20%20%20%20%20(_w%2C%20iters)%2C%20t%20%3D%20run_timed(fn)%0A%20%20%20%20%20%20%20%20sp_lw%5Bkey%5D%20%3D%20%7B%22time_s%22%3A%20t%2C%20%22iters%22%3A%20iters%7D%0A%0A%20%20%20%20print_table(%22Without%20LW%20shrinkage%20(alpha%3D0)%22%2C%20sp_no_lw)%0A%20%20%20%20print_table(f%22With%20LW%20shrinkage%20(alpha%3D%7Balpha_sp%3A.4f%7D)%22%2C%20sp_lw)%0A%0A%20%20%20%20%23%20%E2%94%80%E2%94%80%20Panel%20A%3A%20runtime%20vs%20n%20%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%0A%0A%20%20%20%20print()%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%20%20%20%20print(%22Runtime%20vs%20n%20%20(T%3D2n%2C%20LW%20shrinkage%2C%20long-only%20minimum%20variance)%22)%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%0A%20%20%20%20ns%20%3D%20%5B50%2C%20100%2C%20200%2C%20300%2C%20500%2C%20750%2C%201000%2C%201500%2C%202000%5D%0A%20%20%20%20times%20%3D%20%7Bk%3A%20%5B%5D%20for%20k%20in%20(%22kkt%22%2C%20%22cg%22%2C%20%22nnls%22)%7D%0A%20%20%20%20rng2%20%3D%20np.random.default_rng(0)%0A%20%20%20%20print(f%22%7B'n'%3A%3E6%7D%20%20%7B'kkt'%3A%3E10%7D%20%20%7B'cg'%3A%3E10%7D%20%20%7B'nnls'%3A%3E10%7D%22)%0A%20%20%20%20print(%22-%22%20*%2044)%0A%20%20%20%20for%20n%20in%20ns%3A%0A%20%20%20%20%20%20%20%20T%20%3D%202%20*%20n%0A%20%20%20%20%20%20%20%20R%20%3D%20rng2.standard_normal((T%2C%20n))%0A%20%20%20%20%20%20%20%20alpha%20%3D%20n%20%2F%20(n%20%2B%20T)%0A%20%20%20%20%20%20%20%20bar_lam%20%3D%20float(np.linalg.norm(R%2C%20%22fro%22)%20**%202)%20%2F%20(n%20*%20T)%0A%20%20%20%20%20%20%20%20tgt%20%3D%20bar_lam%20*%20np.eye(n)%0A%20%20%20%20%20%20%20%20_%2C%20t_kkt%20%3D%20run_timed(lambda%20r%3DR%2C%20a%3Dalpha%2C%20t%3Dtgt%3A%20MinVarProblem(r%2C%20alpha%3Da%2C%20target%3Dt).solve_kkt())%0A%20%20%20%20%20%20%20%20_%2C%20t_cg%20%3D%20run_timed(lambda%20r%3DR%2C%20a%3Dalpha%2C%20t%3Dtgt%3A%20MinVarProblem(r%2C%20alpha%3Da%2C%20target%3Dt).solve_cg())%0A%20%20%20%20%20%20%20%20_%2C%20t_nnls%20%3D%20run_timed(lambda%20r%3DR%2C%20a%3Dalpha%2C%20t%3Dtgt%3A%20MinVarProblem(r%2C%20alpha%3Da%2C%20target%3Dt).solve_nnls())%0A%20%20%20%20%20%20%20%20times%5B%22kkt%22%5D.append(t_kkt)%0A%20%20%20%20%20%20%20%20times%5B%22cg%22%5D.append(t_cg)%0A%20%20%20%20%20%20%20%20times%5B%22nnls%22%5D.append(t_nnls)%0A%20%20%20%20%20%20%20%20print(f%22%7Bn%3A%3E6%7D%20%20%7Bt_kkt%3A%3E10.4f%7D%20%20%7Bt_cg%3A%3E10.4f%7D%20%20%7Bt_nnls%3A%3E10.4f%7D%22)%0A%0A%20%20%20%20%23%20%E2%94%80%E2%94%80%20Panel%20B%3A%20iterations%20vs%20shrinkage%20intensity%20alpha%20%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%0A%0A%20%20%20%20n_iter%2C%20T_iter%20%3D%20500%2C%20250%0A%20%20%20%20R_iter%20%3D%20np.random.default_rng(1).standard_normal((T_iter%2C%20n_iter))%0A%20%20%20%20bar_lambda_iter%20%3D%20float(np.linalg.norm(R_iter%2C%20%22fro%22)%20**%202)%20%2F%20(n_iter%20*%20T_iter)%0A%20%20%20%20alphas%20%3D%20np.linspace(0.01%2C%200.99%2C%2040)%0A%20%20%20%20cg_iters_by_alpha%20%3D%20%5B%5D%0A%20%20%20%20print()%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%20%20%20%20print(f%22Iterations%20vs%20alpha%20%20(n%3D%7Bn_iter%7D%2C%20T%3D%7BT_iter%7D%2C%20rank-deficient)%22)%0A%20%20%20%20print(%22%3D%22%20*%2070)%0A%20%20%20%20for%20a%20in%20alphas%3A%0A%20%20%20%20%20%20%20%20tgt_iter%20%3D%20bar_lambda_iter%20*%20np.eye(n_iter)%0A%20%20%20%20%20%20%20%20_%2C%20iters%20%3D%20MinVarProblem(R_iter%2C%20alpha%3Da%2C%20target%3Dtgt_iter).solve_cg()%0A%20%20%20%20%20%20%20%20cg_iters_by_alpha.append(iters)%0A%20%20%20%20%20%20%20%20print(f%22%20%20alpha%3D%7Ba%3A.3f%7D%20%20iters%3D%7Biters%7D%22)%0A%0A%20%20%20%20%23%20%E2%94%80%E2%94%80%20Plot%20%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%0A%0A%20%20%20%20fig%2C%20(ax1%2C%20ax2)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(6.5%2C%202.8))%0A%0A%20%20%20%20colors%20%3D%20%7B%22kkt%22%3A%20%22%231f77b4%22%2C%20%22cg%22%3A%20%22%23ff7f0e%22%2C%20%22nnls%22%3A%20%22%232ca02c%22%7D%0A%20%20%20%20labels%20%3D%20%7B%22kkt%22%3A%20%22KKT%20direct%22%2C%20%22cg%22%3A%20%22CG%20(matrix-free)%22%2C%20%22nnls%22%3A%20%22NNLS%22%7D%0A%20%20%20%20for%20key%20in%20(%22kkt%22%2C%20%22cg%22%2C%20%22nnls%22)%3A%0A%20%20%20%20%20%20%20%20ax1.plot(ns%2C%20times%5Bkey%5D%2C%20marker%3D%22o%22%2C%20markersize%3D3%2C%20label%3Dlabels%5Bkey%5D%2C%20color%3Dcolors%5Bkey%5D)%0A%20%20%20%20ax1.set_xscale(%22log%22)%0A%20%20%20%20ax1.set_yscale(%22log%22)%0A%20%20%20%20ax1.set_xlabel(%22Number%20of%20assets%20%24n%24%22)%0A%20%20%20%20ax1.set_ylabel(%22Wall-clock%20time%20(s)%22)%0A%20%20%20%20ax1.set_title(r%22(a)%20Runtime%20vs.%20%24n%24%20%20(%24T%3D2n%24%2C%20with%20LW%20shrinkage)%22)%0A%20%20%20%20ax1.legend(framealpha%3D0.9)%0A%20%20%20%20ax1.grid(True%2C%20which%3D%22both%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D0.5%2C%20alpha%3D0.7)%0A%0A%20%20%20%20ax2.plot(alphas%2C%20cg_iters_by_alpha%2C%20marker%3D%22o%22%2C%20markersize%3D3%2C%20color%3Dcolors%5B%22cg%22%5D%2C%20label%3Dlabels%5B%22cg%22%5D)%0A%20%20%20%20ax2.set_xlabel(r%22Shrinkage%20intensity%20%24%5Calpha%24%20%20%24(%5Ckappa%24%20decreases%20%24%5Crightarrow)%24%22)%0A%20%20%20%20ax2.set_ylabel(%22CG%20iterations%20to%20convergence%22)%0A%20%20%20%20ax2.set_title(r%22(b)%20Iterations%20vs.%20%24%5Calpha%24%20%20(%24n%3D500%2C%5C%2CT%3D250%24)%22)%0A%20%20%20%20ax2.legend(framealpha%3D0.9)%0A%20%20%20%20ax2.grid(True%2C%20which%3D%22both%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D0.5%2C%20alpha%3D0.7)%0A%0A%20%20%20%20fig.tight_layout(pad%3D1.0)%0A%0A%20%20%20%20folder%20%3D%20Path(__file__).parent%20%2F%20%22graphs%22%0A%20%20%20%20fig.savefig(folder%20%2F%20%22minvar_scaling.pdf%22%2C%20bbox_inches%3D%22tight%22)%0A%20%20%20%20fig.savefig(folder%20%2F%20%22minvar_scaling.png%22%2C%20bbox_inches%3D%22tight%22%2C%20dpi%3D150)%0A%20%20%20%20print()%0A%20%20%20%20print(%22Saved%20graphs%2Fminvar_scaling.pdf%20and%20graphs%2Fminvar_scaling.png%22)%0A%0A%20%20%20%20%23%20%E2%94%80%E2%94%80%20Standalone%20log-log%20Runtime%20vs%20n%20%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%0A%0A%20%20%20%20fig2%2C%20ax%20%3D%20plt.subplots(figsize%3D(4.5%2C%203.2))%0A%0A%20%20%20%20for%20key%20in%20(%22kkt%22%2C%20%22cg%22%2C%20%22nnls%22)%3A%0A%20%20%20%20%20%20%20%20ax.plot(ns%2C%20times%5Bkey%5D%2C%20marker%3D%22o%22%2C%20markersize%3D4%2C%20label%3Dlabels%5Bkey%5D%2C%20color%3Dcolors%5Bkey%5D)%0A%0A%20%20%20%20%23%20Reference%20slope%20lines%20anchored%20to%20the%20KKT%20curve%20at%20n%3D500%0A%20%20%20%20n_arr%20%3D%20np.array(ns%2C%20dtype%3Dfloat)%0A%20%20%20%20anchor_idx%20%3D%20ns.index(500)%0A%20%20%20%20t_anchor%20%3D%20times%5B%22kkt%22%5D%5Banchor_idx%5D%0A%20%20%20%20n_anchor%20%3D%20500.0%0A%20%20%20%20for%20exp%2C%20ls%2C%20lbl%20in%20%5B(2%2C%20%22--%22%2C%20r%22%24O(n%5E2)%24%22)%2C%20(3%2C%20%22%3A%22%2C%20r%22%24O(n%5E3)%24%22)%5D%3A%0A%20%20%20%20%20%20%20%20ax.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20n_arr%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t_anchor%20*%20(n_arr%20%2F%20n_anchor)%20**%20exp%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22gray%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20linestyle%3Dls%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D0.9%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20label%3Dlbl%2C%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20ax.set_xscale(%22log%22)%0A%20%20%20%20ax.set_yscale(%22log%22)%0A%20%20%20%20ax.set_xlabel(%22Number%20of%20assets%20%24n%24%22)%0A%20%20%20%20ax.set_ylabel(%22Wall-clock%20time%20(s)%22)%0A%20%20%20%20ax.set_title(r%22Runtime%20vs.%20%24n%24%20%20(%24T%20%3D%202n%24%2C%20LW%20shrinkage)%22)%0A%20%20%20%20ax.legend(framealpha%3D0.9)%0A%20%20%20%20ax.grid(True%2C%20which%3D%22both%22%2C%20linestyle%3D%22%3A%22%2C%20linewidth%3D0.5%2C%20alpha%3D0.7)%0A%20%20%20%20fig2.tight_layout(pad%3D1.0)%0A%0A%20%20%20%20fig2.savefig(folder%20%2F%20%22minvar_loglog.pdf%22%2C%20bbox_inches%3D%22tight%22)%0A%20%20%20%20fig2.savefig(folder%20%2F%20%22minvar_loglog.png%22%2C%20bbox_inches%3D%22tight%22%2C%20dpi%3D150)%0A%20%20%20%20print(%22Saved%20graphs%2Fminvar_loglog.pdf%20and%20graphs%2Fminvar_loglog.png%22)%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
21427687ef6ecbf1350d52281a429825