chore: update rhiza to v0.18.8#50
Open
tschm wants to merge 31 commits into
Open
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Loop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…handoff Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace explicit Sigma_LW assembly with matrix-free gradient mat.T @ (mat @ w) and estimate the Lipschitz constant via power iteration on mat, both O(nT) per step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ection strategies Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Readers need to know what X-tilde is before seeing it in the algorithms. Also updates the intro section-range reference and the forward-pointer "solvers above" -> "solvers in Section 6". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Define \tbr (missing command, brown text for to-be-revised blocks)
- Redefine \tcr/\tcb/\tcm/\tcg to use {\color{X}#1} instead of
\textcolor{X}{#1} so they can span paragraph breaks
- Fix unclosed $ in Algorithm 3 (Direct Solve) algorithmic block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Abstract now introduces both matrix-free approaches in parallel: CG + active-set (O(sqrt(kappa))) and simplex-projection proximal (loop-free, O(kappa)), with LW shrinkage reducing kappa for both. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Gives the simplex-projection strategy its own algorithm alongside Algorithm 1 (active-set), with matrix-free gradient and O(n log n) simplex projection explicitly annotated per step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also renames the Section 6.4 proximal algorithm label to alg:proximal_detail to avoid conflict with the new Algorithm 2 (alg:proximal) in s4_nonneg.tex; restores \tbr dropped by linter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the subsection heading, algorithm box, and editorial \tcb{} wrapper.
Retains the key observation (paradoxically slower with shrinkage) as a
\paragraph{NNLS baseline.} before the Proximal Gradient subsection.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR syncs the repository with the updated Rhiza template and, as part of that sync, introduces a new proximal-gradient–based solver and supporting test/benchmark/documentation assets.
Changes:
- Add a matrix-free proximal gradient simplex-projection solver (
proximal.py) and expose it via_BaseProblem.solve_proximal. - Add synthetic data generation helper (
simulate_equity_returns) and export it at the package top level. - Add/extend tests and benchmarking notebook content to cover the proximal solver and template updates.
Reviewed changes
Copilot reviewed 17 out of 21 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
src/fast_minimum_variance/_base.py |
Adds CVXPY backend selection and introduces solve_proximal template solver. |
src/fast_minimum_variance/proximal.py |
New simplex projection + proximal gradient implementation. |
src/fast_minimum_variance/data/_simulate.py |
New synthetic equity return simulator. |
src/fast_minimum_variance/data/__init__.py |
Exports synthetic data helper. |
src/fast_minimum_variance/__init__.py |
Re-exports simulate_equity_returns at top level. |
tests/conftest.py |
Adds a shared fixture for test resources directory. |
tests/test_base.py |
Adds template-level tests for solve_proximal. |
tests/test_proximal.py |
New unit + integration tests for simplex projection, proximal solver, and Problem.solve_proximal. |
book/marimo/notebooks/make_minvar_figures.py |
Adds proximal solver to benchmark/figure generation. |
paper/* |
Adds/updates LaTeX paper sources and bibliography for solver discussion. |
.rhiza/template.yml |
Bumps upstream Rhiza template reference. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+172
to
+174
| cvxpy_solver = cp.CLARABEL if backend.lower() == "clarabel" else cp.OSQP | ||
| problem = cp.Problem(cp.Minimize(objective), self._cvxpy_constraints(w, cp)) | ||
| problem.solve(solver=cp.CLARABEL) | ||
| problem.solve(solver=cvxpy_solver) |
Comment on lines
+373
to
+376
| from .proximal import prox_gradient | ||
|
|
||
| if self.target is None: | ||
| p_dense = 2.0 * ((self.X.T @ self.X) / self.t) | ||
| if self.target is not None and self.alpha > 0.0: | ||
| c = 1.0 - self.alpha |
Comment on lines
+72
to
+75
| muu = np.sort(vec)[::-1] | ||
| cummeans = 1 / np.arange(1, len(vec) + 1) * (np.cumsum(muu) - rad) | ||
| rho = max(np.where(muu > cummeans)[0]) | ||
| result: NDArray[np.floating] = np.maximum(vec - cummeans[rho], 0) |
Comment on lines
+54
to
+60
| rng = np.random.default_rng(rng) | ||
| if k is None: | ||
| k = max(3, n // 10) | ||
|
|
||
| # Factor volatilities (daily): market ~1 %, style factors ~0.5 % | ||
| factor_vols = np.concatenate([[0.01], np.full(k - 1, 0.005)]) | ||
|
|
Comment on lines
+238
to
+242
| def test_iters_is_one(self): | ||
| """Iteration count is always 1.""" | ||
| _, iters = _Stub(_X3).solve_proximal() | ||
| assert iters == 1 | ||
|
|
Comment on lines
+121
to
+124
| def test_cla(self, resource_dir) -> None: | ||
| """Test against CLA expected values.""" | ||
| covar = np.genfromtxt(resource_dir / "CLA_Data.csv", delimiter=",", skip_header=1)[3:] | ||
| result, _ = prox_gradient(covar, np.ones(10)) |
Comment on lines
101
to
105
| _, t_kkt = run_timed(lambda r=R, a=alpha, t=tgt: MinVarProblem(r, alpha=a, target=t).solve_kkt()) | ||
| _, t_cg = run_timed(lambda r=R, a=alpha, t=tgt: MinVarProblem(r, alpha=a, target=t).solve_cg()) | ||
| _, t_nnls = run_timed(lambda r=R, a=alpha, t=tgt: MinVarProblem(r, alpha=a, target=t).solve_nnls()) | ||
| _, t_prox = run_timed(lambda r=R, a=alpha, t=tgt: MinVarProblem(r, alpha=a, target=t).solve_proximal()) | ||
| times["kkt"].append(t_kkt) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
template-branchtov0.18.8in.rhiza/template.yml.rhiza/.rhiza-versionto0.16.1make syncto apply upstream template changes