27#include "absl/container/btree_map.h"
28#include "absl/container/flat_hash_map.h"
29#include "absl/log/check.h"
30#include "absl/log/log.h"
31#include "absl/log/vlog_is_on.h"
32#include "absl/numeric/int128.h"
33#include "absl/strings/str_cat.h"
34#include "absl/strings/string_view.h"
35#include "absl/types/span.h"
57 if (!VLOG_IS_ON(1))
return;
58 std::vector<std::pair<std::string, int64_t>> stats;
59 stats.push_back({
"symmetrizer/overflows", num_overflows_});
60 shared_stats_->AddStats(stats);
64 IntegerVariable sum_var, absl::Span<const IntegerVariable> orbit) {
65 CHECK_GT(orbit.size(), 1);
68 const int orbit_index = orbits_.size();
70 orbit_sum_vars_.push_back(sum_var);
74 const int new_size = integer_trail_->NumIntegerVariables().value() / 2;
75 if (var_to_orbit_index_.size() < new_size) {
76 var_to_orbit_index_.resize(new_size, -1);
81 for (
const IntegerVariable var : orbit) {
110 if (!has_symmetry_)
return true;
114 int64_t scaling_factor = 1;
116 const IntegerVariable var = ct->
vars[
i];
120 if (orbit_index == -1 || orbit_sum_vars_[orbit_index] == var) {
127 const int orbit_size = orbits_[orbit_index].size();
130 VLOG(2) <<
"SYMMETRY skip constraint due to overflow";
133 scaling_factor = std::lcm(scaling_factor, orbit_size);
136 if (scaling_factor == 1) {
141 if (folded !=
nullptr) *folded =
true;
149 const IntegerVariable var = ct->
vars[
i];
150 const IntegerValue coeff = ct->
coeffs[
i];
153 if (orbit_index == -1 || orbit_sum_vars_[orbit_index] == var) {
154 const int64_t scaled_coeff =
CapProd(coeff.value(), scaling_factor);
157 VLOG(2) <<
"SYMMETRY skip constraint due to overflow";
160 builder_.AddTerm(var, scaled_coeff);
162 const int64_t orbit_size = orbits_[orbit_index].size();
163 const int64_t factor = scaling_factor / orbit_size;
164 const int64_t scaled_coeff =
CapProd(coeff.value(), factor);
167 VLOG(2) <<
"SYMMETRY skip constraint due to overflow";
170 builder_.AddTerm(orbit_sum_vars_[orbit_index], scaled_coeff);
177 VLOG(2) <<
"SYMMETRY skip constraint due to lb/ub overflow";
180 if (!builder_.BuildIntoConstraintAndCheckOverflow(
181 ct->
lb * scaling_factor, ct->
ub * scaling_factor, ct)) {
183 VLOG(2) <<
"SYMMETRY skip constraint due to overflow";
191 VLOG(2) <<
"SYMMETRY skip constraint due to overflow factor = "
203 if (!has_symmetry_)
return -1;
208 if (!has_symmetry_)
return false;
210 return orbit_index >= 0 && orbit_sum_vars_[orbit_index] == var;
214 IntegerVariable var)
const {
215 if (!has_symmetry_)
return true;
217 return orbit_index == -1 || orbit_sum_vars_[orbit_index] == var;
222const LinearConstraintManager::ConstraintIndex kInvalidConstraintIndex(-1);
228 for (
int i = 0;
i < num_terms; ++
i) {
238 if (!VLOG_IS_ON(1))
return;
241 std::vector<std::pair<std::string, int64_t>> cut_stats;
242 for (
const auto& entry : type_to_num_cuts_) {
243 cut_stats.push_back({absl::StrCat(
"cut/", entry.first), entry.second});
248void LinearConstraintManager::RescaleActiveCounts(
const double scaling_factor) {
249 for (ConstraintIndex
i(0);
i < constraint_infos_.size(); ++
i) {
250 constraint_infos_[
i].active_count *= scaling_factor;
252 constraint_active_count_increase_ *= scaling_factor;
253 VLOG(3) <<
"Rescaled active counts by " << scaling_factor;
256bool LinearConstraintManager::MaybeRemoveSomeInactiveConstraints(
257 glop::BasisState* solution_state) {
258 if (solution_state->IsEmpty())
return false;
259 const glop::RowIndex num_rows(lp_constraints_.size());
260 const glop::ColIndex num_cols =
261 solution_state->statuses.size() - RowToColIndex(num_rows);
263 for (
int i = 0;
i < num_rows; ++
i) {
264 const ConstraintIndex constraint_index = lp_constraints_[
i];
265 if (constraint_infos_[constraint_index].constraint.num_terms == 0) {
271 constraint_infos_[constraint_index].is_in_lp =
false;
282 solution_state->statuses[num_cols + glop::ColIndex(
i)];
284 constraint_infos_[constraint_index].inactive_count++;
285 if (constraint_infos_[constraint_index].inactive_count >
286 sat_parameters_.max_consecutive_inactive_count()) {
287 constraint_infos_[constraint_index].is_in_lp =
false;
292 constraint_infos_[constraint_index].inactive_count = 0;
295 lp_constraints_[new_size] = constraint_index;
296 solution_state->statuses[num_cols + glop::ColIndex(new_size)] = row_status;
299 const int num_removed_constraints = lp_constraints_.size() - new_size;
300 lp_constraints_.resize(new_size);
301 solution_state->statuses.resize(num_cols + glop::ColIndex(new_size));
302 if (num_removed_constraints > 0) {
303 VLOG(3) <<
"Removed " << num_removed_constraints <<
" constraints";
305 return num_removed_constraints > 0;
316 SimplifyConstraint(&ct);
323 if (symmetrizer_->HasSymmetry() &&
324 !symmetrizer_->FoldLinearConstraint(&ct, folded)) {
325 return kInvalidConstraintIndex;
330 const size_t key = ComputeHashOfTerms(ct);
331 if (equiv_constraints_.contains(key)) {
332 const ConstraintIndex ct_index = equiv_constraints_[key];
333 if (constraint_infos_[ct_index].constraint.IsEqualIgnoringBounds(ct)) {
334 bool tightened =
false;
335 if (ct.
lb > constraint_infos_[ct_index].constraint.lb) {
337 if (constraint_infos_[ct_index].is_in_lp) current_lp_is_changed_ =
true;
338 constraint_infos_[ct_index].constraint.lb = ct.
lb;
340 if (ct.
ub < constraint_infos_[ct_index].constraint.ub) {
342 if (constraint_infos_[ct_index].is_in_lp) current_lp_is_changed_ =
true;
343 constraint_infos_[ct_index].constraint.ub = ct.
ub;
345 if (added !=
nullptr) *added = tightened;
347 ++num_merged_constraints_;
348 FillDerivedFields(&constraint_infos_[ct_index]);
354 if (added !=
nullptr) *added =
true;
355 const ConstraintIndex ct_index(constraint_infos_.size());
359 FillDerivedFields(&ct_info);
361 equiv_constraints_[key] = ct_index;
362 ct_info.
active_count = constraint_active_count_increase_;
363 constraint_infos_.push_back(std::move(ct_info));
368 IntegerValue new_lb) {
369 const ConstraintIndex index = lp_constraints_[index_in_lp.value()];
372 ++num_constraint_updates_;
373 current_lp_is_changed_ =
true;
379 IntegerValue new_ub) {
380 const ConstraintIndex index = lp_constraints_[index_in_lp.value()];
383 ++num_constraint_updates_;
384 current_lp_is_changed_ =
true;
389void LinearConstraintManager::ComputeObjectiveParallelism(
390 const ConstraintIndex ct_index) {
391 CHECK(objective_is_defined_);
393 if (!objective_norm_computed_) {
394 objective_l2_norm_ = std::sqrt(sum_of_squared_objective_coeffs_);
395 objective_norm_computed_ =
true;
397 CHECK_GT(objective_l2_norm_, 0.0);
399 constraint_infos_[ct_index].objective_parallelism_computed =
true;
400 if (constraint_infos_[ct_index].l2_norm == 0.0) {
401 constraint_infos_[ct_index].objective_parallelism = 0.0;
405 const LinearConstraint& lc = constraint_infos_[ct_index].constraint;
406 double unscaled_objective_parallelism = 0.0;
407 for (
int i = 0;
i < lc.num_terms; ++
i) {
408 const IntegerVariable var = lc.vars[
i];
409 const auto it = objective_map_.find(var);
410 if (it == objective_map_.end())
continue;
411 unscaled_objective_parallelism += it->second *
ToDouble(lc.coeffs[
i]);
413 const double objective_parallelism =
414 unscaled_objective_parallelism /
415 (constraint_infos_[ct_index].l2_norm * objective_l2_norm_);
416 constraint_infos_[ct_index].objective_parallelism =
417 std::abs(objective_parallelism);
423 std::string extra_info) {
424 ++num_add_cut_calls_;
428 const double violation =
433 if (violation / l2_norm < 1e-4) {
434 VLOG(3) <<
"BAD Cut '" << type_name <<
"'"
437 <<
" norm=" << l2_norm <<
" violation=" << violation
438 <<
" eff=" << violation / l2_norm <<
" " << extra_info;
449 const ConstraintIndex ct_index =
Add(std::move(ct), &added);
453 if (!added)
return false;
457 constraint_infos_[ct_index].is_deletable =
true;
459 VLOG(2) <<
"Cut '" << type_name <<
"'"
460 <<
" size=" << constraint_infos_[ct_index].constraint.num_terms
463 <<
" norm=" << l2_norm <<
" violation=" << violation
464 <<
" eff=" << violation / l2_norm <<
" " << extra_info;
467 num_deletable_constraints_++;
468 type_to_num_cuts_[type_name]++;
472void LinearConstraintManager::PermanentlyRemoveSomeConstraints() {
473 std::vector<double> deletable_constraint_counts;
474 for (ConstraintIndex
i(0);
i < constraint_infos_.size(); ++
i) {
475 if (constraint_infos_[
i].is_deletable && !constraint_infos_[
i].is_in_lp) {
476 deletable_constraint_counts.push_back(constraint_infos_[
i].active_count);
479 if (deletable_constraint_counts.empty())
return;
480 std::sort(deletable_constraint_counts.begin(),
481 deletable_constraint_counts.end());
485 double active_count_threshold = std::numeric_limits<double>::infinity();
487 deletable_constraint_counts.size()) {
488 active_count_threshold =
492 ConstraintIndex new_size(0);
493 equiv_constraints_.clear();
494 util_intops::StrongVector<ConstraintIndex, ConstraintIndex> index_mapping(
495 constraint_infos_.size());
496 int num_deleted_constraints = 0;
497 for (ConstraintIndex
i(0);
i < constraint_infos_.size(); ++
i) {
498 if (constraint_infos_[
i].is_deletable && !constraint_infos_[
i].is_in_lp &&
499 constraint_infos_[
i].active_count <= active_count_threshold &&
500 num_deleted_constraints < sat_parameters_.cut_cleanup_target()) {
501 ++num_deleted_constraints;
506 constraint_infos_[new_size] = std::move(constraint_infos_[
i]);
508 index_mapping[
i] = new_size;
511 equiv_constraints_[constraint_infos_[new_size].hash] = new_size;
514 constraint_infos_.resize(new_size.value());
517 for (
int i = 0;
i < lp_constraints_.size(); ++
i) {
518 lp_constraints_[
i] = index_mapping[lp_constraints_[
i]];
521 if (num_deleted_constraints > 0) {
522 VLOG(3) <<
"Constraint manager cleanup: #deleted:"
523 << num_deleted_constraints;
525 num_deletable_constraints_ -= num_deleted_constraints;
529 IntegerValue coeff) {
530 if (coeff == IntegerValue(0))
return;
531 objective_is_defined_ =
true;
536 const double coeff_as_double =
ToDouble(coeff);
537 const auto insert = objective_map_.insert({var, coeff_as_double});
539 <<
"SetObjectiveCoefficient() called twice with same variable";
540 sum_of_squared_objective_coeffs_ += coeff_as_double * coeff_as_double;
545 bool term_changed =
false;
547 IntegerValue min_sum(0);
548 IntegerValue max_sum(0);
549 IntegerValue max_magnitude(0);
553 for (
int i = 0;
i < num_terms; ++
i) {
554 const IntegerVariable var = ct->
vars[
i];
555 const IntegerValue coeff = ct->
coeffs[
i];
561 if (lb == ub)
continue;
564 const IntegerValue magnitude =
IntTypeAbs(coeff);
565 max_magnitude = std::max(max_magnitude, magnitude);
566 min_magnitude = std::min(min_magnitude, magnitude);
568 min_sum += coeff * lb;
569 max_sum += coeff * ub;
571 min_sum += coeff * ub;
572 max_sum += coeff * lb;
577 IntegerValue fixed_part = 0;
578 if (new_size < num_terms) {
580 ++num_shortened_constraints_;
582 for (
int i = 0;
i < num_terms; ++
i) {
583 const IntegerVariable var = ct->
vars[
i];
584 const IntegerValue coeff = ct->
coeffs[
i];
585 const IntegerValue lb = integer_trail_.LevelZeroLowerBound(var);
586 const IntegerValue ub = integer_trail_.LevelZeroUpperBound(var);
588 fixed_part += coeff * lb;
591 ct->
vars[new_size] = var;
592 ct->
coeffs[new_size] = coeff;
600 if (min_sum + fixed_part >= ct->
lb && max_sum + fixed_part <= ct->ub) {
608 ct->
lb = std::max(ct->
lb, min_sum + fixed_part);
609 ct->
ub = std::min(ct->
ub, max_sum + fixed_part);
610 ct->
lb -= fixed_part;
611 ct->
ub -= fixed_part;
619 const IntegerValue threshold_ub = max_sum - ct->
ub;
620 const IntegerValue threshold_lb = ct->
lb - min_sum;
621 const IntegerValue threshold = std::max(threshold_lb, threshold_ub);
622 CHECK_GT(threshold, 0);
626 if (threshold_ub > 0 && threshold_lb > 0 && threshold_lb != threshold_ub) {
627 if (max_magnitude > std::min(threshold_lb, threshold_ub)) {
628 ++num_split_constraints_;
634 const IntegerValue second_threshold = std::max(
635 {
CeilRatio(threshold, IntegerValue(2)), threshold - min_magnitude,
636 std::min(threshold_lb, threshold_ub)});
637 if (max_magnitude > second_threshold) {
639 for (
int i = 0;
i < num_terms; ++
i) {
644 const IntegerValue coeff = ct->
coeffs[
i];
645 const IntegerVariable var = ct->
vars[
i];
646 const IntegerValue lb = integer_trail_.LevelZeroLowerBound(var);
647 const IntegerValue ub = integer_trail_.LevelZeroUpperBound(var);
648 if (coeff > threshold) {
650 ++num_coeff_strenghtening_;
652 ct->
ub -= (coeff - threshold) * ub;
653 ct->
lb -= (coeff - threshold) * lb;
654 }
else if (coeff > second_threshold && coeff < threshold) {
656 ++num_coeff_strenghtening_;
657 ct->
coeffs[
i] = second_threshold;
658 ct->
ub -= (coeff - second_threshold) * ub;
659 ct->
lb -= (coeff - second_threshold) * lb;
660 }
else if (coeff < -threshold) {
662 ++num_coeff_strenghtening_;
664 ct->
ub -= (coeff + threshold) * lb;
665 ct->
lb -= (coeff + threshold) * ub;
666 }
else if (coeff < -second_threshold && coeff > -threshold) {
668 ++num_coeff_strenghtening_;
669 ct->
coeffs[
i] = -second_threshold;
670 ct->
ub -= (coeff + second_threshold) * lb;
671 ct->
lb -= (coeff + second_threshold) * ub;
679void LinearConstraintManager::FillDerivedFields(ConstraintInfo* info) {
680 IntegerValue min_sum(0);
681 IntegerValue max_sum(0);
682 const int num_terms = info->constraint.num_terms;
683 for (
int i = 0;
i < num_terms; ++
i) {
684 const IntegerVariable var = info->constraint.vars[
i];
685 const IntegerValue coeff = info->constraint.coeffs[
i];
686 const IntegerValue lb = integer_trail_.LevelZeroLowerBound(var);
687 const IntegerValue ub = integer_trail_.LevelZeroUpperBound(var);
689 min_sum += coeff * lb;
690 max_sum += coeff * ub;
692 min_sum += coeff * ub;
693 max_sum += coeff * lb;
696 info->constraint.lb = std::max(min_sum, info->constraint.lb);
697 info->constraint.ub = std::min(max_sum, info->constraint.ub);
698 CHECK_NE(
CapSub(info->constraint.ub.value(), info->constraint.lb.value()),
699 std::numeric_limits<int64_t>::max());
700 info->lb_is_trivial = min_sum >= info->constraint.lb;
701 info->ub_is_trivial = max_sum <= info->constraint.ub;
705 int* num_new_constraints) {
706 VLOG(3) <<
"Enter ChangeLP, scan " << constraint_infos_.size()
708 const double saved_dtime = dtime_;
709 std::vector<std::pair<ConstraintIndex, double>> new_constraints_by_score;
710 std::vector<double> new_constraints_efficacies;
711 std::vector<double> new_constraints_orthogonalities;
713 const bool simplify_constraints =
714 integer_trail_.num_level_zero_enqueues() > last_simplification_timestamp_;
715 last_simplification_timestamp_ = integer_trail_.num_level_zero_enqueues();
720 bool rescale_active_count =
false;
721 const double tolerance = 1e-6;
722 for (ConstraintIndex
i(0);
i < constraint_infos_.size(); ++
i) {
724 if (simplify_constraints &&
725 SimplifyConstraint(&constraint_infos_[
i].constraint)) {
726 ++num_simplifications_;
734 constraint_infos_[
i].objective_parallelism_computed =
false;
735 constraint_infos_[
i].l2_norm =
737 FillDerivedFields(&constraint_infos_[
i]);
739 if (constraint_infos_[
i].is_in_lp) current_lp_is_changed_ =
true;
740 equiv_constraints_.erase(constraint_infos_[
i].hash);
741 constraint_infos_[
i].hash =
742 ComputeHashOfTerms(constraint_infos_[
i].constraint);
746 equiv_constraints_[constraint_infos_[
i].hash] =
i;
749 if (constraint_infos_[
i].is_in_lp)
continue;
754 1.7e-9 *
static_cast<double>(constraint_infos_[
i].constraint.num_terms);
755 const double activity =
757 const double lb_violation =
758 ToDouble(constraint_infos_[
i].constraint.lb) - activity;
759 const double ub_violation =
760 activity -
ToDouble(constraint_infos_[
i].constraint.ub);
761 const double violation = std::max(lb_violation, ub_violation);
762 if (violation >= tolerance) {
763 constraint_infos_[
i].inactive_count = 0;
764 if (objective_is_defined_ &&
765 !constraint_infos_[
i].objective_parallelism_computed) {
766 ComputeObjectiveParallelism(
i);
767 }
else if (!objective_is_defined_) {
768 constraint_infos_[
i].objective_parallelism = 0.0;
771 const double score = violation / constraint_infos_[
i].l2_norm +
772 constraint_infos_[
i].objective_parallelism;
773 new_constraints_by_score.push_back({
i, score});
775 if (constraint_infos_[
i].is_deletable) {
776 constraint_infos_[
i].active_count += constraint_active_count_increase_;
777 if (constraint_infos_[
i].active_count >
778 sat_parameters_.cut_max_active_count_value()) {
779 rescale_active_count =
true;
786 if (solution_state !=
nullptr) {
787 const glop::RowIndex num_rows(lp_constraints_.size());
788 const glop::ColIndex num_cols =
789 solution_state->
statuses.
size() - RowToColIndex(num_rows);
791 for (
int i = 0;
i < num_rows; ++
i) {
792 const ConstraintIndex constraint_index = lp_constraints_[
i];
794 solution_state->
statuses[num_cols + glop::ColIndex(
i)];
796 constraint_infos_[constraint_index].is_deletable) {
797 constraint_infos_[constraint_index].active_count +=
798 constraint_active_count_increase_;
799 if (constraint_infos_[constraint_index].active_count >
800 sat_parameters_.cut_max_active_count_value()) {
801 rescale_active_count =
true;
807 if (rescale_active_count) {
808 CHECK_GT(sat_parameters_.cut_max_active_count_value(), 0.0);
809 RescaleActiveCounts(1.0 / sat_parameters_.cut_max_active_count_value());
813 constraint_active_count_increase_ *=
814 1.0 / sat_parameters_.cut_active_count_decay();
819 if (MaybeRemoveSomeInactiveConstraints(solution_state)) {
820 current_lp_is_changed_ =
true;
833 const int kBlowupFactor = 4;
834 const int current_size =
static_cast<int>(new_constraints_by_score.size());
835 int constraint_limit =
836 std::min(sat_parameters_.new_constraints_batch_size(), current_size);
837 if (lp_constraints_.empty()) {
838 constraint_limit = std::min(1000, current_size);
840 VLOG(3) <<
" - size = " << current_size <<
", limit = " << constraint_limit;
842 std::stable_sort(new_constraints_by_score.begin(),
843 new_constraints_by_score.end(),
844 [&](std::pair<ConstraintIndex, double> a,
845 std::pair<ConstraintIndex, double>
b) {
846 return a.second > b.second;
848 if (new_constraints_by_score.size() > kBlowupFactor * constraint_limit) {
849 VLOG(3) <<
"Resize candidate constraints from "
850 << new_constraints_by_score.size() <<
" down to "
851 << kBlowupFactor * constraint_limit;
852 new_constraints_by_score.resize(kBlowupFactor * constraint_limit);
857 ConstraintIndex last_added_candidate = kInvalidConstraintIndex;
858 std::vector<double> orthogonality_score(new_constraints_by_score.size(), 1.0);
859 for (
int i = 0;
i < constraint_limit; ++
i) {
864 double best_score = 0.0;
865 ConstraintIndex best_candidate = kInvalidConstraintIndex;
866 for (
int j = 0; j < new_constraints_by_score.size(); ++j) {
868 if (time_limit_check.
LimitReached())
return current_lp_is_changed_;
870 const ConstraintIndex new_index = new_constraints_by_score[j].first;
871 if (constraint_infos_[new_index].is_in_lp)
continue;
873 if (last_added_candidate != kInvalidConstraintIndex) {
874 const double current_orthogonality =
876 constraint_infos_[last_added_candidate].constraint,
877 constraint_infos_[new_index].constraint)) /
878 (constraint_infos_[last_added_candidate].l2_norm *
879 constraint_infos_[new_index].l2_norm));
880 orthogonality_score[j] =
881 std::min(orthogonality_score[j], current_orthogonality);
889 if (orthogonality_score[j] <
890 sat_parameters_.min_orthogonality_for_lp_constraints()) {
897 orthogonality_score[j] + new_constraints_by_score[j].second;
898 CHECK_GE(score, 0.0);
899 if (score > best_score || best_candidate == kInvalidConstraintIndex) {
901 best_candidate = new_index;
905 if (best_candidate != kInvalidConstraintIndex) {
907 constraint_infos_[best_candidate].is_in_lp =
true;
912 current_lp_is_changed_ =
true;
913 lp_constraints_.push_back(best_candidate);
914 last_added_candidate = best_candidate;
921 if (num_new_constraints !=
nullptr) {
922 *num_new_constraints = num_added;
926 VLOG(3) <<
"Added " << num_added <<
" constraints.";
933 if (num_deletable_constraints_ > sat_parameters_.max_num_cuts()) {
934 PermanentlyRemoveSomeConstraints();
937 time_limit_->AdvanceDeterministicTime(dtime_ - saved_dtime);
941 if (current_lp_is_changed_) {
942 current_lp_is_changed_ =
false;
949 for (ConstraintIndex
i(0);
i < constraint_infos_.size(); ++
i) {
950 if (constraint_infos_[
i].is_in_lp)
continue;
951 if (constraint_infos_[
i].constraint.num_terms == 0)
continue;
953 constraint_infos_[
i].is_in_lp =
true;
954 lp_constraints_.push_back(
i);
961 if (debug_solution ==
nullptr || debug_solution->
proto_values.empty()) {
965 absl::int128 activity(0);
967 const IntegerVariable var = cut.
vars[
i];
968 const IntegerValue coeff = cut.
coeffs[
i];
974 absl::int128(coeff.value()) * debug_solution->
ivar_values[var].value();
976 if (activity > cut.
ub.value() || activity < cut.
lb.value()) {
978 LOG(INFO) <<
"activity " << activity <<
" not in [" << cut.
lb <<
","
986 if (reduced_costs_is_cached_)
return;
987 reduced_costs_is_cached_ =
true;
989 const absl::int128 ub = reduced_cost_constraint_.ub.value();
990 absl::int128 level_zero_lb = 0;
991 for (
int i = 0;
i < reduced_cost_constraint_.num_terms; ++
i) {
992 IntegerVariable var = reduced_cost_constraint_.vars[
i];
993 IntegerValue coeff = reduced_cost_constraint_.coeffs[
i];
999 const IntegerValue lb = integer_trail_.LevelZeroLowerBound(var);
1000 level_zero_lb += absl::int128(coeff.value()) * absl::int128(lb.value());
1002 if (lb == integer_trail_.LevelZeroUpperBound(var))
continue;
1003 const LiteralIndex lit = integer_encoder_.GetAssociatedLiteral(
1006 reduced_costs_map_[
Literal(lit)] = coeff;
1009 const absl::int128 gap = ub - level_zero_lb;
1011 reduced_costs_gap_ = gap;
1013 reduced_costs_gap_ = 0;
1014 reduced_costs_map_.clear();
1023 cuts_.Add({std::string(name), std::move(ct)}, normalized_violation);
1027 for (CutCandidate& candidate : *cuts_.MutableUnorderedElements()) {
1028 manager->
AddCut(std::move(candidate.cut), candidate.name);
void resize(IntType size)
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
~LinearConstraintManager()
ConstraintIndex Add(LinearConstraint ct, bool *added=nullptr, bool *folded=nullptr)
bool ChangeLp(glop::BasisState *solution_state, int *num_new_constraints=nullptr)
bool AddCut(LinearConstraint ct, std::string type_name, std::string extra_info="")
bool UpdateConstraintUb(glop::RowIndex index_in_lp, IntegerValue new_ub)
void CacheReducedCostsInfo()
bool DebugCheckConstraint(const LinearConstraint &cut)
bool UpdateConstraintLb(glop::RowIndex index_in_lp, IntegerValue new_lb)
void AddAllConstraintsToLp()
void SetObjectiveCoefficient(IntegerVariable var, IntegerValue coeff)
bool FoldLinearConstraint(LinearConstraint *ct, bool *folded=nullptr)
int OrbitIndex(IntegerVariable var) const
void AddSymmetryOrbit(IntegerVariable sum_var, absl::Span< const IntegerVariable > orbit)
~LinearConstraintSymmetrizer()
bool IsOrbitSumVar(IntegerVariable var) const
bool AppearInFoldedProblem(IntegerVariable var) const
::int32_t cut_cleanup_target() const
void TransferToManager(LinearConstraintManager *manager)
void AddCut(LinearConstraint ct, absl::string_view name, const util_intops::StrongVector< IntegerVariable, double > &lp_solution)
double ComputeActivity(const LinearConstraint &constraint, const util_intops::StrongVector< IntegerVariable, double > &values)
void DivideByGCD(LinearConstraint *constraint)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
IntType IntTypeAbs(IntType t)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
const LiteralIndex kNoLiteralIndex(-1)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
bool PossibleOverflow(const IntegerTrail &integer_trail, const LinearConstraint &constraint)
IntegerValue ComputeInfinityNorm(const LinearConstraint &ct)
double ComputeL2Norm(const LinearConstraint &ct)
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
void MakeAllVariablesPositive(LinearConstraint *constraint)
bool NoDuplicateVariable(const LinearConstraint &ct)
bool VariableIsPositive(IntegerVariable i)
double ToDouble(IntegerValue value)
double ScalarProduct(const LinearConstraint &ct1, const LinearConstraint &ct2)
bool AtMinOrMaxInt64(int64_t x)
int64_t CapSub(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
uint64_t Hash(uint64_t num, uint64_t c)
VariableStatusRow statuses
std::vector< int64_t > proto_values
util_intops::StrongVector< IntegerVariable, bool > ivar_has_value
util_intops::StrongVector< IntegerVariable, IntegerValue > ivar_values
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
LinearConstraint constraint
std::unique_ptr< IntegerValue[]> coeffs
std::unique_ptr< IntegerVariable[]> vars
std::string DebugString() const
absl::Span< const IntegerVariable > VarsAsSpan() const
double NormalizedViolation(const util_intops::StrongVector< IntegerVariable, double > &lp_values) const