47 return std::max(1e-6, down_branch) * std::max(1e-6, up_branch);
49 const double min_value = std::min(up_branch, down_branch);
50 const double max_value = std::max(up_branch, down_branch);
51 const double mu = 1.0 / 6.0;
52 return (1.0 - mu) * min_value + mu * max_value;
66 const int num_vars = integer_trail_->NumIntegerVariables().value();
67 pseudo_costs_.resize(num_vars);
68 is_relevant_.resize(num_vars,
false);
69 scores_.resize(num_vars, 0.0);
74 if (objective !=
nullptr) {
75 objective_var_ = objective->objective_var;
103 absl::Span<const double> lp_values) {
104 bound_changes_.clear();
105 for (
const IntegerLiteral l : encoder_->GetIntegerLiterals(decision)) {
109 if (l.var < lp_values.size()) {
111 std::max(0.0,
ToDouble(l.bound) - lp_values[l.var.value()]);
113 bound_changes_.push_back(entry);
117 for (
const auto [var, value] : encoder_->GetEqualityLiterals(decision)) {
122 bound_changes_.push_back(entry);
130 (-value) - integer_trail_->LowerBound(
NegationOf(var));
131 bound_changes_.push_back(entry);
143 IntegerVariable var, absl::Span<const double> lp_values) {
146 const IntegerValue lb = integer_trail_->LowerBound(var);
147 const IntegerValue ub = integer_trail_->UpperBound(var);
153 const double lp_value = lp_values[var.value()];
154 double down_fractionality = lp_value - std::floor(lp_value);
155 IntegerValue down_target = IntegerValue(std::floor(lp_value));
157 down_fractionality = 1.0;
158 down_target = ub - 1;
159 }
else if (lp_value <=
ToDouble(lb)) {
160 down_fractionality = 0.0;
164 result.
is_integer = std::abs(lp_value - std::round(lp_value)) < 1e-6;
168 const int max_index = std::max(var.value(),
NegationOf(var).value());
169 if (max_index < average_unit_objective_increase_.size()) {
172 average_unit_objective_increase_[
NegationOf(var)].CurrentAverage();
173 result.
up_score = (1.0 - down_fractionality) *
174 average_unit_objective_increase_[var].CurrentAverage();
177 const int reliablitity = std::min(
178 average_unit_objective_increase_[var].NumRecords(),
179 average_unit_objective_increase_[
NegationOf(var)].NumRecords());
187 IntegerValue objective_increase) {
188 const double relative_increase =
189 ToDouble(objective_increase) /
static_cast<double>(reason.size());
190 for (
const Literal lit : reason) {
191 if (lit.Index() >= lit_pseudo_costs_.size()) {
192 lit_pseudo_costs_.resize(lit.Index() + 1);
194 lit_pseudo_costs_[lit].AddData(relative_increase);
228 const ObjectiveInfo new_info = GetCurrentObjectiveInfo();
236 if (saved_info_.lp_at_optimal) {
239 for (
const auto [var, lb_change, lp_increase] : bound_changes_) {
240 if (lp_increase < 1e-6)
continue;
241 if (var >= average_unit_objective_increase_.size()) {
242 average_unit_objective_increase_.resize(var + 1);
244 average_unit_objective_increase_[var].AddData(obj_increase / lp_increase);
249 if (conflict)
return;
252 const IntegerValue obj_bound_improvement =
253 (new_info.lb - saved_info_.lb) + (saved_info_.ub - new_info.ub);
254 DCHECK_GE(obj_bound_improvement, 0);
255 if (obj_bound_improvement == IntegerValue(0))
return;
257 for (
const auto [var, lb_change, lp_increase] : bound_changes_) {
258 if (lb_change == IntegerValue(0))
continue;
260 if (var >= pseudo_costs_.size()) {
262 const int new_size = std::max(var,
NegationOf(var)).value() + 1;
263 is_relevant_.resize(new_size,
false);
264 scores_.resize(new_size, 0.0);
268 pseudo_costs_[var].AddData(
ToDouble(obj_bound_improvement) /
272 const IntegerVariable negative_var =
NegationOf(positive_var);
273 const int64_t count = pseudo_costs_[positive_var].NumRecords() +
274 pseudo_costs_[negative_var].NumRecords();
275 if (count >= parameters_.pseudo_cost_reliability_threshold()) {
276 scores_[positive_var] =
278 if (!is_relevant_[positive_var]) {
279 is_relevant_[positive_var] =
true;
280 relevant_variables_.push_back(positive_var);
291 double best_score = -std::numeric_limits<double>::infinity();
296 for (
const IntegerVariable positive_var : relevant_variables_) {
297 const IntegerValue lb = integer_trail_->LowerBound(positive_var);
298 const IntegerValue ub = integer_trail_->UpperBound(positive_var);
299 if (lb >= ub)
continue;
300 if (scores_[positive_var] > best_score) {
301 chosen_var = positive_var;
302 best_score = scores_[positive_var];