26 absl::BitGenRef random,
28 : variables_info_(variables_info),
30 reduced_costs_(reduced_costs),
34 bool nothing_to_recompute,
const UpdateRow& update_row,
35 Fractional cost_variation, std::vector<ColIndex>* bound_flip_candidates,
36 ColIndex* entering_col) {
56 const Fractional threshold = nothing_to_recompute
57 ? parameters_.minimum_acceptable_pivot()
58 : parameters_.ratio_test_zero_threshold();
64 parameters_.harris_tolerance_ratio() *
71 parameters_.degenerate_ministep_factor() *
79 const Fractional coeff = (cost_variation > 0.0) ? update_coefficient[
col]
80 : -update_coefficient[
col];
84 if (can_decrease.
IsSet(
col) && coeff > threshold) {
86 if (-reduced_costs[
col] > harris_ratio * coeff)
continue;
88 harris_ratio, (-reduced_costs[
col] + harris_tolerance) / coeff);
89 harris_ratio =
std::max(minimum_delta / coeff, harris_ratio);
91 breakpoints_.push_back(ColWithRatio(
col, -reduced_costs[
col], coeff));
97 if (can_increase.
IsSet(
col) && coeff < -threshold) {
99 if (reduced_costs[
col] > harris_ratio * -coeff)
continue;
101 harris_ratio, (reduced_costs[
col] + harris_tolerance) / -coeff);
102 harris_ratio =
std::max(minimum_delta / -coeff, harris_ratio);
104 breakpoints_.push_back(ColWithRatio(
col, reduced_costs[
col], -coeff));
114 std::make_heap(breakpoints_.begin(), breakpoints_.end());
128 bound_flip_candidates->clear();
131 Fractional variation_magnitude = std::abs(cost_variation);
132 equivalent_entering_choices_.clear();
133 while (!breakpoints_.empty()) {
134 const ColWithRatio top = breakpoints_.front();
135 if (top.ratio > harris_ratio)
break;
148 if (variation_magnitude > threshold) {
149 if (is_boxed[top.col]) {
150 variation_magnitude -=
152 if (variation_magnitude > threshold) {
153 bound_flip_candidates->push_back(top.col);
154 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
155 breakpoints_.pop_back();
164 if (top.coeff_magnitude >= best_coeff) {
169 harris_ratio, top.ratio + harris_tolerance / top.coeff_magnitude);
176 std::max(harris_ratio, minimum_delta / top.coeff_magnitude);
178 if (top.coeff_magnitude == best_coeff && top.ratio == step) {
180 equivalent_entering_choices_.push_back(top.col);
182 equivalent_entering_choices_.clear();
183 best_coeff = top.coeff_magnitude;
184 *entering_col = top.col;
194 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
195 breakpoints_.pop_back();
199 if (!equivalent_entering_choices_.empty()) {
200 equivalent_entering_choices_.push_back(*entering_col);
202 equivalent_entering_choices_[std::uniform_int_distribution<int>(
203 0, equivalent_entering_choices_.size() - 1)(random_)];
205 stats_.num_perfect_ties.Add(equivalent_entering_choices_.size()));
212 const Fractional pivot_limit = parameters_.minimum_acceptable_pivot();
213 if (best_coeff < pivot_limit && !bound_flip_candidates->empty()) {
216 for (
int i = bound_flip_candidates->size() - 1; i >= 0; --i) {
217 const ColIndex
col = (*bound_flip_candidates)[i];
218 if (std::abs(update_coefficient[
col]) < pivot_limit)
continue;
220 VLOG(1) <<
"Used bound flip to avoid bad pivot. Before: " << best_coeff
221 <<
" now: " << std::abs(update_coefficient[
col]);
231 bool nothing_to_recompute,
const UpdateRow& update_row,
232 Fractional cost_variation, ColIndex* entering_col) {
240 breakpoints_.clear();
243 const Fractional threshold = nothing_to_recompute
244 ? parameters_.minimum_acceptable_pivot()
245 : parameters_.ratio_test_zero_threshold();
249 parameters_.harris_tolerance_ratio() * dual_feasibility_tolerance;
251 parameters_.degenerate_ministep_factor() * dual_feasibility_tolerance;
266 if (std::abs(update_coefficient[
col]) < threshold)
continue;
274 const Fractional coeff = (cost_variation > 0.0) ? update_coefficient[
col]
275 : -update_coefficient[
col];
279 if (std::abs(reduced_costs[
col]) <= dual_feasibility_tolerance) {
281 if (coeff > 0 && !can_decrease.
IsSet(
col))
continue;
282 if (coeff < 0 && !can_increase.
IsSet(
col))
continue;
287 if (coeff * reduced_costs[
col] > 0.0) {
288 breakpoints_.push_back(ColWithRatio(
291 harris_tolerance - std::abs(reduced_costs[
col])),
297 if (coeff * reduced_costs[
col] > 0.0)
continue;
301 breakpoints_.push_back(ColWithRatio(
302 col, std::abs(reduced_costs[
col]) + harris_tolerance, std::abs(coeff)));
306 std::make_heap(breakpoints_.begin(), breakpoints_.end());
317 Fractional improvement = std::abs(cost_variation);
318 while (!breakpoints_.empty()) {
319 const ColWithRatio top = breakpoints_.front();
322 DCHECK(top.ratio > step ||
323 (top.ratio == step && top.coeff_magnitude <= pivot_magnitude));
324 if (top.ratio > step && top.coeff_magnitude >= pivot_magnitude) {
325 *entering_col = top.col;
327 pivot_magnitude = top.coeff_magnitude;
329 improvement -= top.coeff_magnitude;
334 if (can_decrease.
IsSet(top.col) && can_increase.
IsSet(top.col) &&
335 std::abs(reduced_costs[top.col]) > threshold) {
336 improvement -= top.coeff_magnitude;
339 if (improvement <= 0.0)
break;
340 std::pop_heap(breakpoints_.begin(), breakpoints_.end());
341 breakpoints_.pop_back();
#define DCHECK_NE(val1, val2)
#define DCHECK(condition)
#define VLOG(verboselevel)
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
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
@ UPPER_AND_LOWER_BOUNDED
const ColIndex kInvalidCol(-1)
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)