|
| 1 | +# HiGHS - User bound and cost scaling |
| 2 | + |
| 3 | +User bound and cost scaling have been introduced to assess solver |
| 4 | +performance if a user's model were better scaled. It is achieved using |
| 5 | +the integer `HighsOptions::user_bound_scale` and |
| 6 | +`HighsOptions::user_cost_scale` options, where the scaling factor |
| 7 | +itself is two to the power of the option value. For simplicity, the |
| 8 | +scaling is applied to the incumbent model - as if the model had been |
| 9 | +well scaled by the user. |
| 10 | + |
| 11 | +Scaling of costs is simple, since all costs are scaled. Scaling of LPs |
| 12 | +is also simple since all finite column and row bounds are scaled, so |
| 13 | +the constraint matrix is unchanged. However, nonzero (finite) bounds |
| 14 | +on non-continuous variables cannot be scaled, since it would change |
| 15 | +the number of feasible values. For a non-continuous variable, its |
| 16 | +contributions to the objective and constraint activites are scaled by |
| 17 | +scaling the cost coefficient and matrix values. |
| 18 | + |
| 19 | +In summary, the incumbent data affected by user bound and cost scaling |
| 20 | +are as follows |
| 21 | + |
| 22 | +- User bound scaling affects |
| 23 | + - Costs of non-continuous variables — using `userScaleCosts` |
| 24 | + - Matrix coefficients of non-continuous variables — using `userScaleMatrix` |
| 25 | + - Bounds of continuous variables — using `userScaleColBounds` |
| 26 | + - All row bounds — using `userScaleRowBounds` |
| 27 | +- User cost scaling affects |
| 28 | + - All column costs — using `userScaleCosts` |
| 29 | + |
| 30 | +The only exception is the case of changes driven by a |
| 31 | +`HighsIndexCollection`, where scaling is performed on individual |
| 32 | +entries |
| 33 | + |
| 34 | +## Where user scaling takes place |
| 35 | + |
| 36 | +User scaling typically takes place when a model has been passed to |
| 37 | +HiGHS and the values of `user_bound_scale` or `user_cost_scale` are |
| 38 | +nonzero, or when the values of `user_bound_scale` or `user_cost_scale` |
| 39 | +are changed after a model has been passed to HiGHS. However, for |
| 40 | +consistency, when the incumbent model has been scaled that must be |
| 41 | +maintained when other operations take place. |
| 42 | + |
| 43 | +Although scaling is more likely to be done to reduce the magnitude of |
| 44 | +bounds and costs, extreme scaling up can make increase the magnitude |
| 45 | +of bounds and costs beyond the value at which HiGHS considers them to |
| 46 | +be infinite. This (arguably) changes the model fundamentally. Hence, |
| 47 | +whenever user scaling is applied, an initial pass is made to determine |
| 48 | +whether it generates infinite bounds or costs or large matrix values, |
| 49 | +returning an error if this occurs. If they only create small matrix |
| 50 | +values, then a warning is issued. |
| 51 | + |
| 52 | +### `Highs::passModel` |
| 53 | + |
| 54 | +When a model is passed to HiGHS, if `user_bound_scale` or |
| 55 | +`user_cost_scale` are nonzero then their use is considered. If they |
| 56 | +create no infinte bounds or costs, or large matrix values, then the |
| 57 | +user scaling is applied, otherwise an error is returned. If they only |
| 58 | +create small matrix values, then the user scaling is applied, and a |
| 59 | +warning is issued. |
| 60 | + |
| 61 | +### `Highs::addColsInterface` |
| 62 | + |
| 63 | +When new columns are added to a model, they have no integrality, so |
| 64 | +the scaling of their bounds and costs is simple. Hence, |
| 65 | +`user_bound_scale` is applied uniformly to the (local) lower and upper |
| 66 | +bounds of the new columns, and `user_cost_scale` is applied uniformly |
| 67 | +to the (local) costs of the new columns. |
| 68 | + |
| 69 | +### `Highs::addRowsInterface` |
| 70 | + |
| 71 | +When new rows are added to a model, any column integrality must be |
| 72 | +respected. Hence `user_bound_scale` must be applied to the columns of |
| 73 | +non-continuous variables in the (local) matrix, and must be applied |
| 74 | +uniformly to the lower and upper bounds of the new rows |
| 75 | + |
| 76 | +### `Highs::changeIntegralityInterface` |
| 77 | + |
| 78 | +When integrality changes, the simplest thing to do is first remove any |
| 79 | +scaling specific to non-continuous variables — by using the negation |
| 80 | +of `user_bound_scale` to scale the costs and matrix coefficient for |
| 81 | +non-continuous variables. Then, after updating the integrality, use |
| 82 | +`user_bound_scale` to scale the costs and matrix coefficient for |
| 83 | +non-continuous variables. |
| 84 | + |
| 85 | +### `Highs::changeCostsInterface` |
| 86 | + |
| 87 | +When costs change, `user_bound_scale` must be applied to the changed |
| 88 | +costs of non-continuous variables, and `user_cost_scale` must be |
| 89 | +applied uniformly. |
| 90 | + |
| 91 | +### `Highs::changeColBoundsInterface` |
| 92 | + |
| 93 | +When column bounds change, `user_bound_scale` must be applied to the |
| 94 | +changed bounds of continuous variables |
| 95 | + |
| 96 | +### `Highs::changeRowBoundsInterface` |
| 97 | + |
| 98 | +When row bounds change, `user_bound_scale` must be applied uniformly |
| 99 | +to the changed bounds |
| 100 | + |
| 101 | +### `Highs::changeCoefficientInterface |
| 102 | + |
| 103 | +The coefficient is scaled using `user_bound_scale` if is corresponds |
| 104 | +to a non-continuous variable |
| 105 | + |
| 106 | +### `Highs::optionChangeAction` |
| 107 | + |
| 108 | +When `user_bound_scale` or `user_cost_scale` change (the difference |
| 109 | +in) this value must be applied as for a whole model. Since this is |
| 110 | +typically the first application of user scaling, there is a check for |
| 111 | +infinte bounds or costs, and whichever of `user_bound_scale` and |
| 112 | +`user_cost_scale` causes then is rejected with an error return. |
| 113 | + |
| 114 | +### `Highs::passModel` |
| 115 | + |
| 116 | + |
0 commit comments