OSQP Settings Sequence Data Frame
Source:vignettes/osqp-settings-sequence-dataframe.Rmd
osqp-settings-sequence-dataframe.Rmd
Data frame containing a sequence of OSQP settings for
tsbalancing()
specified with argument
osqp_settings_df
. The package includes two predefined OSQP
settings sequence data frames that are presented below.
Data frame default_osqp_sequence
Fast and effective sequence of OSQP settings that should be suitable
for accurately solving most time series balancing problems. It is the
default value of tsbalancing()
argument
osqp_settings_df
.
#> max_iter sigma eps_abs eps_rel eps_prim_inf eps_dual_inf polish scaling
#> 1 4,000 1.00e-09 1.00e-06 1.00e-06 1.00e-07 1.00e-07 TRUE 0
#> 2 10,000 1.00e-15 1.00e-12 1.00e-12 1.00e-13 1.00e-13 TRUE 0
#> 3 10,000 1.00e-15 1.00e-12 1.00e-12 1.00e-13 1.00e-13 TRUE 0
#> 4 10,000 2.22e-16 2.22e-16 2.22e-16 2.22e-16 2.22e-16 TRUE 0
#> prior_scaling require_polished
#> 1 TRUE TRUE
#> 2 TRUE TRUE
#> 3 FALSE FALSE
#> 4 TRUE FALSE
Data frame
alternate_osqp_sequence
Alternative slower sequence of OSQP settings that could help achieve
more precision, when needed, especially when combined with argument
full_sequence = TRUE
.
#> max_iter sigma eps_abs eps_rel eps_prim_inf eps_dual_inf polish scaling
#> 1 10,000 1.00e-15 1.00e-12 1.00e-12 1.00e-13 1.00e-13 TRUE 0
#> 2 10,000 1.00e-15 1.00e-12 1.00e-12 1.00e-13 1.00e-13 TRUE 10
#> 3 10,000 1.00e-12 1.00e-09 1.00e-09 1.00e-10 1.00e-10 TRUE 0
#> 4 10,000 1.00e-12 1.00e-09 1.00e-09 1.00e-10 1.00e-10 TRUE 10
#> 5 10,000 1.00e-09 1.00e-06 1.00e-06 1.00e-07 1.00e-07 TRUE 0
#> 6 10,000 1.00e-09 1.00e-06 1.00e-06 1.00e-07 1.00e-07 TRUE 10
#> 7 10,000 1.00e-06 1.00e-03 1.00e-03 1.00e-04 1.00e-04 TRUE 0
#> 8 10,000 1.00e-06 1.00e-03 1.00e-03 1.00e-04 1.00e-04 TRUE 10
#> 9 10,000 2.22e-16 2.22e-16 2.22e-16 2.22e-16 2.22e-16 TRUE 0
#> 10 10,000 2.22e-16 2.22e-16 2.22e-16 2.22e-16 2.22e-16 TRUE 10
#> 11 10,000 1.00e-15 1.00e-12 1.00e-12 1.00e-13 1.00e-13 TRUE 0
#> 12 10,000 1.00e-12 1.00e-09 1.00e-09 1.00e-10 1.00e-10 TRUE 0
#> 13 10,000 1.00e-09 1.00e-06 1.00e-06 1.00e-07 1.00e-07 TRUE 0
#> 14 10,000 1.00e-06 1.00e-03 1.00e-03 1.00e-04 1.00e-04 TRUE 0
#> 15 10,000 2.22e-16 2.22e-16 2.22e-16 2.22e-16 2.22e-16 TRUE 0
#> prior_scaling require_polished
#> 1 FALSE TRUE
#> 2 FALSE TRUE
#> 3 FALSE TRUE
#> 4 FALSE TRUE
#> 5 FALSE TRUE
#> 6 FALSE TRUE
#> 7 FALSE TRUE
#> 8 FALSE TRUE
#> 9 FALSE TRUE
#> 10 FALSE TRUE
#> 11 TRUE TRUE
#> 12 TRUE TRUE
#> 13 TRUE TRUE
#> 14 TRUE TRUE
#> 15 TRUE TRUE
Details
With the exception of prior_scaling
and
require_polished
, all columns of the data frame must
correspond to a OSQP setting. Default OSQP values are used for any
setting not specified in this data frame. Visit https://osqp.org/docs/interfaces/solver_settings.html
for all available OSQP settings. Note that the OSQP verbose
setting is actually controlled through tsbalancing()
arguments quiet
and display_level
(i.e.,
column verbose
in a OSQP settings sequence data
frame would be ignored).
Each row of a OSQP settings sequence data frame represents
one attempt at solving a balancing problem with the corresponding OSQP
settings. The solving sequence stops as soon as a valid solution is
obtained (a solution for which all constraint discrepancies are smaller
or equal to the tolerance specified with tsbalancing()
argument validation_tol
) unless column
require_polished = TRUE
, in which case a polished solution
from OSQP (status_polish = 1
) would also be required to
stop the sequence. Constraint discrepancies correspond to \mathrm{max}(0, l - Ax, Ax - u) with
constraints defined as l \le Ax \le u.
In the event where a satisfactory solution cannot be obtained after
having gone through the entire sequence, tsbalancing()
returns the solution that generated the smallest total constraint
discrepancies among valid solutions, if any, or among all solutions,
otherwise. Note that running the entire solving sequence can be
enforced by specifying tsbalancing()
argument
full_sequence = TRUE
. Rows with column
prior_scaling = TRUE
have the problem data scaled prior to
solving with OSQP, using the average of the free (nonbinding) problem
values as the scaling factor.
In addition to specifying a custom-made OSQP settings sequence
data frame with argument osqp_settings_df
, one can
also specify osqp_settings_df = NULL
which would result in
a single solving attempt with default OSQP values for all settings along
with prior_scaling = FALSE
and
require_polished = FALSE
. Note that it is recommended,
however, to first try data frames default_osqp_sequence
and
alternate_osqp_sequence
, along with
full_sequence = TRUE
if necessary, before considering other
alternatives.
Recommended Approach
Start with the default tsbalancing()
solving sequence
(osqp_settings_df = default_osqp_sequence
and
full_sequence = FALSE
). Then, if more precision is needed,
try with:
full_sequence = TRUE
osqp_settings_df = alternate_osqp_sequence
-
osqp_settings_df = alternate_osqp_sequence
andfull_sequence = TRUE
In practice, specifying full_sequence = TRUE
should be
enough when more precision is needed (at the expense of execution time,
obviously). Only in rare occasions should you need to use the
alternate_osqp_sequence
data frame, which will often be
even more costly in terms of execution time especially when combined
with full_sequence = TRUE
.
Guiding Principles
The following is a summary of the lessons learned while developing
tsbalancing()
and experimenting with the OSQP solver. They
are the guiding principles that lead to both OSQP settings sequence
data frames presented earlier. Note that these observations apply
to time series balancing problems as solved by
tsbalancing()
and may not directly apply to other types of
quadratic problems.
- Data preconditioning options available in OSQP (with the
scaling
setting) are not sufficient for some (badly scaled) problems. External (prior) data scaling (prior_scaling = TRUE
) is sometimes necessary for OSQP to converge at a decent pace and generate precise enough solutions in a reasonable number of iterations. - Prior data scaling often reduces execution time (the required number of iterations to achieve the specified precision) and greatly increases the likelihood of polished solutions.
- Polished solutions are always very precise, even when prior data scaling is performed (i.e., the solution in the original scale will usually still be precise enough).
- While polished solutions from prior-scaled data are usually more precise than unpolished solutions from non prior-scaled data, the most precise solutions correspond to polished solutions from non prior-scaled data.
- Smaller
sigma
and tolerance (eps_*
) settings result in more precise solutions but take longer to run (require more iterations). - Enough precision is usually obtained after 10,000 iterations with
small values for the
sigma
and tolerance (eps_*
) settings. - The default OSQP values for
alpha
and the various settings associated to \rho (*rho*
) are sufficient (they work well). Reducing thesigma
and tolerance (eps_*
) settings and performing prior data scaling is sufficient to obtain precise solutions in a reasonable number of iterations. - Keeping the same scale between the
sigma
and tolerance (eps_*
) settings as the default OSQP values works well and is used in both OSQP settings sequence data frames, i.e.:eps_abs = eps_rel = 1,000 * sigma
eps_prim_inf = eps_dual_inf = 100 * sigma
- (and consequently)
eps_abs = eps_rel = 10 * eps_prim_inf = 10 * eps_dual_inf
- The machine epsilon (
.Machine$double.eps
) for thesigma
and tolerance (eps_*
) settings, which basically forces the maximum number of iterations, is used as a last resort in both OSQP settings sequence data frames.
Summary - default sequence (data frame
default_osqp_sequence
)
- Geared towards achieving both fast and precise solutions.
- First try to get (fast) polished solutions on prior-scaled data before attempting solving the original (non-scaled) problem data.
- Make a final attempt on prior-scaled data with the machine
epsilon for the
sigma
and tolerance (eps_*
) settings.
Summary - alternative sequence (data frame
alternate_osqp_sequence
)
- Geared towards achieving precise solutions at the expense of execution time.
- Somewhat similar to a brute force or try all
approach (especially when combined with
full_sequence = TRUE
). - Small
sigma
and tolerance (eps_*
) settings that gradually increase, with the machine epsilon as a last attempt. - Polished solutions are required for every step of the sequence (the best unpolished solution is returned if no polished solution could be obtained at the end of the entire sequence).
- Maximum of 10,000 iterations for every step of the sequence
- First try to get polished solutions from non prior-scaled data (the most precise solutions), then try with prior-scaled data.