Skip to content

feat: warm start support#219

Open
Milias wants to merge 1 commit intooxfordcontrol:mainfrom
Milias:feat/warm-start-support
Open

feat: warm start support#219
Milias wants to merge 1 commit intooxfordcontrol:mainfrom
Milias:feat/warm-start-support

Conversation

@Milias
Copy link
Copy Markdown

@Milias Milias commented Apr 10, 2026

Hello!

I noticed that by default it is not possible to do warm start, and since the change was relatively limited I decided to try it out here. Issue #206 is directly related.

The results are relatively good, especially when the previous solution is quite close to the new one. If the new one is far from the old, the internal state is no longer valid and it needs a cold start anyway. This can be managed from the outside of this crate depending on how people use it.

The table below gives an idea of improvements for a 3 * N problem. The "perturbation" is to check what happens when the input parameters are slightly different. Note that in general the larger the perturbation, the lower the speedup. This is because I'm doing ~6 iterations in warm startup, seeing that it does not converge or any other issue, then starting all over from cold.

The difference between "warm" and "persistent" is that in the latter the solver is constructed once and then update_q() and update_b() are used.

┌─────┬──────────────┬───────────────┬───────────────┬───────────────┬─────────┬────────┐                                                
│  N  │ Perturbation │ Clarabel Cold │ Clarabel Warm │  Persistent   │ Speedup │ Error  │
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 10  │ small        │ 222us / 12it  │ 100us / 6it   │ 82us / 6it    │ 2.7x    │ 7.2e-8 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 10  │ medium       │ 227us / 12it  │ 208us / 16it  │ 193us / 16it  │ 1.2x    │ 6.4e-8 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 10  │ large        │ 223us / 12it  │ 288us / 17it  │ 263us / 17it  │ 0.8x    │ 5.3e-6 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 50  │ small        │ 1.6ms / 13it  │ 1.2ms / 14it  │ 1.1ms / 14it  │ 1.4x    │ 5.6e-6 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 50  │ medium       │ 1.6ms / 13it  │ 1.7ms / 18it  │ 1.6ms / 18it  │ 1.0x    │ 2.5e-5 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 50  │ large        │ 1.7ms / 14it  │ 2.4ms / 29it  │ 2.3ms / 29it  │ 0.7x    │ 1.1e-8 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 100 │ small        │ 5.2ms / 13it  │ 3.9ms / 14it  │ 3.6ms / 14it  │ 1.5x    │ 9.5e-5 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 100 │ medium       │ 5.2ms / 13it  │ 6.6ms / 20it  │ 6.2ms / 20it  │ 0.8x    │ 4.4e-5 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 100 │ large        │ 5.5ms / 14it  │ 9.0ms / 26it  │ 8.7ms / 26it  │ 0.6x    │ 2.3e-5 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 200 │ small        │ 22.8ms / 13it │ 18.5ms / 13it │ 17.4ms / 13it │ 1.3x    │ 2.8e-5 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 200 │ medium       │ 23.3ms / 14it │ 31.3ms / 28it │ 30.1ms / 28it │ 0.8x    │ 5.0e-6 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 200 │ large        │ 24.3ms / 15it │ 46.4ms / 30it │ 45.8ms / 30it │ 0.5x    │ 2.5e-7 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 500 │ small        │ 264ms / 15it  │ 240ms / 18it  │ 231ms / 18it  │ 1.1x    │ 1.5e-7 │                                                
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 500 │ medium       │ 279ms / 16it  │ 423ms / 23it  │ 414ms / 23it  │ 0.7x    │ 7.3e-7 │
├─────┼──────────────┼───────────────┼───────────────┼───────────────┼─────────┼────────┤                                                
│ 500 │ large        │ 280ms / 16it  │ 567ms / 35it  │ 575ms / 35it  │ 0.5x    │ 1.0e-5 │
└─────┴──────────────┴───────────────┴───────────────┴───────────────┴─────────┴────────┘

It's the first time contributing to this repository, so please let me know if you would like anything done differently! Happy to follow your preferences.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 10, 2026

CLA assistant check
All committers have signed the CLA.

…ol#206)

Add a `warm_start_skip` boolean setting (default false) that skips
default variable initialization in `solve()`, enabling warm-starting
from a previous solution.

When enabled, the solver uses whatever values are in `solver.variables`
instead of calling `default_start()`. Internal-form variables are
cached into `solver.prev_vars` before post-process unscaling, so users
can restore them for a subsequent warm-started solve.

- Add `warm_start_skip` to DefaultSettings, FFI settings, and Python bindings
- Add `set_warm_start_skip()` convenience method on Solver
- Cache pre-unscale variables into `prev_vars` for warm-start restoration
- Add integration tests verifying correctness, convergence, and toggle behavior
- Update CHANGELOG

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Milias Milias force-pushed the feat/warm-start-support branch from d83c556 to e2740a9 Compare April 10, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants