Skip to content

feat: active-set stepsize boosting - #108

Open
ZedongPeng wants to merge 1 commit into
MIT-Lu-Lab:mainfrom
ZedongPeng:feat/active-set-boost
Open

feat: active-set stepsize boosting#108
ZedongPeng wants to merge 1 commit into
MIT-Lu-Lab:mainfrom
ZedongPeng:feat/active-set-boost

Conversation

@ZedongPeng

Copy link
Copy Markdown
Collaborator

Summary

Late in a solve most variables sit clamped at a bound and most rows are inactive. The operator restricted to the remaining free variables and binding rows has a smaller maximum singular value than the full constraint matrix, so the stepsize can be raised above the global 1/‖A‖ bound. This PR adds that boost, enabled by default.

  • New src/active_set_boost.cu: tracks which variables stayed clamped and which rows stayed binding over a sliding window of asb_window_iter iterations. Once the worst relative residual falls below asb_activation_tol, it estimates the maximum singular value of the masked operator by power iteration and raises the step to asb_safety_factor / sv, provided the increase is at least asb_min_raise_ratio.
  • Safety net: an anchor iterate is saved before each raise. If the fixed-point error grows past (1 + asb_divergence_margin)x its value at the raise, the anchor is restored, the solver restarts and the step is capped. After asb_max_reverts reverts the boost turns off for the rest of the solve.
  • Eleven --asb_* CLI flags and matching Python parameters, documented in README.md and python/README.md. --no_active_set_boost disables it. The result reports ASB Step Raise Count, ASB Revert Count and ASB Power Iterations.

Also in this PR

  • The power-iteration estimator becomes a reusable context (sv_estimator_create / _run / _free) instead of a one-shot call, since the boost re-estimates repeatedly and needs to keep its buffers, pass a mask and warm-start.
  • compute_infeasibility_information() used state->dual_slack as scratch. That was safe before, but the window kernel reads that vector to tell clamped variables from free ones, so the ray certificate now writes to its own infeasibility_dual_scratch.
  • Parameter ranges now live in one place, the new cupdlpx_validate_parameters(). The duplicated rules in python/cupdlpx/model.py and _core_bindings.cpp are removed, and optimize() calls it too, so the CLI and C API get the full range checks for the first time. Side effects: setParam validates the whole set and commits only on success, an unknown key now raises instead of being ignored, and error messages include the offending value.
  • New --debug flag (implies verbose) adding primal_weight and, with the boost on, step_size and the free/binding counts to the iteration log.
  • Iteration log refactor: the print-frequency test moves into display_iteration_stats(), display_iteration_header() is split out, and the residuals are now computed before the first row so iteration 0 no longer prints 0.0e+00.
  • Minor: sync_step_sizes_to_gpu() exported for the revert path, three missing HIP mappings, and test/test_interface.c Test 9 passes the objective_sense argument that Fix: handle MPS OBJSENSE MAXIMIZE in reader #93 added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant