29 absl::BitGenRef random,
31 : variables_info_(variables_info),
33 reduced_costs_(reduced_costs),
37 bool nothing_to_recompute,
const UpdateRow& update_row,
38 Fractional cost_variation, std::vector<ColIndex>* bound_flip_candidates,
39 ColIndex* entering_col) {
59 const Fractional threshold = nothing_to_recompute
60 ? parameters_.minimum_acceptable_pivot()
61 : parameters_.ratio_test_zero_threshold();
63 Fractional variation_magnitude = std::abs(cost_variation) - threshold;
69 parameters_.harris_tolerance_ratio() *
76 parameters_.degenerate_ministep_factor() *
84 const Fractional coeff = (cost_variation > 0.0) ? update_coefficients[
col]
85 : -update_coefficients[
col];
88 if (can_decrease.
IsSet(
col) && coeff > threshold) {
91 if (-reduced_costs[
col] > harris_ratio * coeff)
continue;
92 entry = ColWithRatio(
col, -reduced_costs[
col], coeff);
93 }
else if (can_increase.
IsSet(
col) && coeff < -threshold) {
96 if (reduced_costs[
col] > harris_ratio * -coeff)
continue;
97 entry = ColWithRatio(
col, reduced_costs[
col], -coeff);
103 std::max(minimum_delta / entry.coeff_magnitude,
104 entry.ratio + harris_tolerance / entry.coeff_magnitude);
105 if (hr < harris_ratio) {
109 if (
delta >= variation_magnitude) {
117 breakpoints_.push_back(entry);
125 std::make_heap(breakpoints_.begin(), breakpoints_.end());
139 bound_flip_candidates->clear();
142 equivalent_entering_choices_.clear();
143 while (!breakpoints_.empty()) {
144 const ColWithRatio top = breakpoints_.front();
145 if (top.ratio > harris_ratio)
break;
158 if (variation_magnitude > 0.0) {
159 if (is_boxed[top.col]) {
160 variation_magnitude -=
162 if (variation_magnitude > 0.0) {
163 bound_flip_candidates->push_back(top.col);
164 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
165 breakpoints_.pop_back();
174 if (top.coeff_magnitude >= best_coeff) {
185 std::max(minimum_delta / top.coeff_magnitude,
186 top.ratio + harris_tolerance / top.coeff_magnitude));
188 if (top.coeff_magnitude == best_coeff && top.ratio == step) {
190 equivalent_entering_choices_.push_back(top.col);
192 equivalent_entering_choices_.clear();
193 best_coeff = top.coeff_magnitude;
194 *entering_col = top.col;
204 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
205 breakpoints_.pop_back();
209 if (!equivalent_entering_choices_.empty()) {
210 equivalent_entering_choices_.push_back(*entering_col);
212 equivalent_entering_choices_[std::uniform_int_distribution<int>(
213 0, equivalent_entering_choices_.size() - 1)(random_)];
215 stats_.num_perfect_ties.Add(equivalent_entering_choices_.size()));
222 const Fractional pivot_limit = parameters_.minimum_acceptable_pivot();
223 if (best_coeff < pivot_limit && !bound_flip_candidates->empty()) {
226 for (
int i = bound_flip_candidates->size() - 1; i >= 0; --i) {
227 const ColIndex
col = (*bound_flip_candidates)[i];
228 if (std::abs(update_coefficients[
col]) < pivot_limit)
continue;
230 VLOG(1) <<
"Used bound flip to avoid bad pivot. Before: " << best_coeff
231 <<
" now: " << std::abs(update_coefficients[
col]);
241 bool nothing_to_recompute,
const UpdateRow& update_row,
242 Fractional cost_variation, ColIndex* entering_col) {
250 breakpoints_.clear();
253 const Fractional threshold = nothing_to_recompute
254 ? parameters_.minimum_acceptable_pivot()
255 : parameters_.ratio_test_zero_threshold();
259 parameters_.harris_tolerance_ratio() * dual_feasibility_tolerance;
261 parameters_.degenerate_ministep_factor() * dual_feasibility_tolerance;
276 if (std::abs(update_coefficients[
col]) < threshold)
continue;
284 const Fractional coeff = (cost_variation > 0.0) ? update_coefficients[
col]
285 : -update_coefficients[
col];
289 if (std::abs(reduced_costs[
col]) <= dual_feasibility_tolerance) {
291 if (coeff > 0 && !can_decrease.
IsSet(
col))
continue;
292 if (coeff < 0 && !can_increase.
IsSet(
col))
continue;
297 if (coeff * reduced_costs[
col] > 0.0) {
298 breakpoints_.push_back(ColWithRatio(
301 harris_tolerance - std::abs(reduced_costs[
col])),
307 if (coeff * reduced_costs[
col] > 0.0)
continue;
311 breakpoints_.push_back(ColWithRatio(
312 col, std::abs(reduced_costs[
col]) + harris_tolerance, std::abs(coeff)));
316 std::make_heap(breakpoints_.begin(), breakpoints_.end());
327 Fractional improvement = std::abs(cost_variation);
328 while (!breakpoints_.empty()) {
329 const ColWithRatio top = breakpoints_.front();
332 DCHECK(top.ratio > step ||
333 (top.ratio == step && top.coeff_magnitude <= pivot_magnitude));
334 if (top.ratio > step && top.coeff_magnitude >= pivot_magnitude) {
335 *entering_col = top.col;
337 pivot_magnitude = top.coeff_magnitude;
339 improvement -= top.coeff_magnitude;
344 if (can_decrease.
IsSet(top.col) && can_increase.
IsSet(top.col) &&
345 std::abs(reduced_costs[top.col]) > threshold) {
346 improvement -= top.coeff_magnitude;
349 if (improvement <= 0.0)
break;
350 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
351 breakpoints_.pop_back();
bool IsSet(IndexType i) const
EnteringVariable(const VariablesInfo &variables_info, absl::BitGenRef random, ReducedCosts *reduced_costs)
ABSL_MUST_USE_RESULT Status DualPhaseIChooseEnteringColumn(bool nothing_to_recompute, const UpdateRow &update_row, Fractional cost_variation, ColIndex *entering_col)
void SetParameters(const GlopParameters ¶meters)
ABSL_MUST_USE_RESULT Status DualChooseEnteringColumn(bool nothing_to_recompute, const UpdateRow &update_row, Fractional cost_variation, std::vector< ColIndex > *bound_flip_candidates, ColIndex *entering_col)
const DenseRow & GetReducedCosts()
Fractional GetDualFeasibilityTolerance() const
ConstView const_view() const
const DenseRow & GetCoefficients() const
const ColIndexVector & GetNonZeroPositions() const
const DenseBitRow & GetNonBasicBoxedVariables() const
Fractional GetBoundDifference(ColIndex col) const
const DenseBitRow & GetCanIncreaseBitRow() const
const DenseBitRow & GetCanDecreaseBitRow() const
const VariableTypeRow & GetTypeRow() const
constexpr ColIndex kInvalidCol(-1)
@ UPPER_AND_LOWER_BOUNDED
Collection of objects used to extend the Constraint Solver library.
#define IF_STATS_ENABLED(instructions)
#define SCOPED_TIME_STAT(stats)
#define GLOP_RETURN_ERROR_IF_NULL(arg)
#define VLOG(verboselevel)