24 #include "absl/strings/str_cat.h"
52 void ScaleConstraint(
const std::vector<double>& var_scaling,
53 MPConstraintProto* mp_constraint) {
54 const int num_terms = mp_constraint->coefficient_size();
55 for (
int i = 0; i < num_terms; ++i) {
56 const int var_index = mp_constraint->var_index(i);
57 mp_constraint->set_coefficient(
58 i, mp_constraint->coefficient(i) / var_scaling[var_index]);
62 void ApplyVarScaling(
const std::vector<double> var_scaling,
63 MPModelProto* mp_model) {
64 const int num_variables = mp_model->variable_size();
65 for (
int i = 0; i < num_variables; ++i) {
66 const double scaling = var_scaling[i];
67 const MPVariableProto& mp_var = mp_model->variable(i);
68 const double old_lb = mp_var.lower_bound();
69 const double old_ub = mp_var.upper_bound();
70 const double old_obj = mp_var.objective_coefficient();
71 mp_model->mutable_variable(i)->set_lower_bound(old_lb * scaling);
72 mp_model->mutable_variable(i)->set_upper_bound(old_ub * scaling);
73 mp_model->mutable_variable(i)->set_objective_coefficient(old_obj / scaling);
75 for (MPConstraintProto& mp_constraint : *mp_model->mutable_constraint()) {
76 ScaleConstraint(var_scaling, &mp_constraint);
78 for (MPGeneralConstraintProto& general_constraint :
79 *mp_model->mutable_general_constraint()) {
80 switch (general_constraint.general_constraint_case()) {
81 case MPGeneralConstraintProto::kIndicatorConstraint:
82 ScaleConstraint(var_scaling,
83 general_constraint.mutable_indicator_constraint()
84 ->mutable_constraint());
86 case MPGeneralConstraintProto::kAndConstraint:
87 case MPGeneralConstraintProto::kOrConstraint:
92 LOG(FATAL) <<
"Scaling unsupported for general constraint of type "
93 << general_constraint.general_constraint_case();
101 MPModelProto* mp_model) {
102 const int num_variables = mp_model->variable_size();
103 std::vector<double> var_scaling(num_variables, 1.0);
104 for (
int i = 0; i < num_variables; ++i) {
105 if (mp_model->variable(i).is_integer())
continue;
106 const double lb = mp_model->variable(i).lower_bound();
107 const double ub = mp_model->variable(i).upper_bound();
108 const double magnitude =
std::max(std::abs(lb), std::abs(ub));
109 if (magnitude == 0 || magnitude > max_bound)
continue;
110 var_scaling[i] =
std::min(scaling, max_bound / magnitude);
112 ApplyVarScaling(var_scaling, mp_model);
120 const double initial_x = x;
126 if (std::abs(q * initial_x - std::round(q * initial_x)) < q * tolerance) {
130 const int new_q = prev_q +
static_cast<int>(std::floor(x)) * q;
144 double GetIntegralityMultiplier(
const MPModelProto& mp_model,
145 const std::vector<double>& var_scaling,
int var,
146 int ct_index,
double tolerance) {
147 DCHECK(!mp_model.variable(
var).is_integer());
148 const MPConstraintProto&
ct = mp_model.constraint(ct_index);
149 double multiplier = 1.0;
150 double var_coeff = 0.0;
151 const double max_multiplier = 1e4;
152 for (
int i = 0; i <
ct.var_index().size(); ++i) {
153 if (
var ==
ct.var_index(i)) {
154 var_coeff =
ct.coefficient(i);
158 DCHECK(mp_model.variable(
ct.var_index(i)).is_integer());
162 multiplier *
ct.coefficient(i) / var_scaling[
ct.var_index(i)];
165 if (multiplier == 0 || multiplier > max_multiplier)
return 0.0;
167 DCHECK_NE(var_coeff, 0.0);
170 for (
const double bound : {
ct.lower_bound(),
ct.upper_bound()}) {
171 if (!std::isfinite(
bound))
continue;
172 if (std::abs(std::round(
bound * multiplier) -
bound * multiplier) >
173 tolerance * multiplier) {
177 return std::abs(multiplier * var_coeff);
183 MPModelProto* mp_model) {
184 const int num_variables = mp_model->variable_size();
185 std::vector<double> var_scaling(num_variables, 1.0);
187 int initial_num_integers = 0;
188 for (
int i = 0; i < num_variables; ++i) {
189 if (mp_model->variable(i).is_integer()) ++initial_num_integers;
191 VLOG(1) <<
"Initial num integers: " << initial_num_integers;
194 const double tolerance = 1e-6;
195 std::vector<int> constraint_queue;
197 const int num_constraints = mp_model->constraint_size();
198 std::vector<int> constraint_to_num_non_integer(num_constraints, 0);
199 std::vector<std::vector<int>> var_to_constraints(num_variables);
200 for (
int i = 0; i < num_constraints; ++i) {
201 const MPConstraintProto& mp_constraint = mp_model->constraint(i);
203 for (
const int var : mp_constraint.var_index()) {
204 if (!mp_model->variable(
var).is_integer()) {
205 var_to_constraints[
var].push_back(i);
206 constraint_to_num_non_integer[i]++;
209 if (constraint_to_num_non_integer[i] == 1) {
210 constraint_queue.push_back(i);
213 VLOG(1) <<
"Initial constraint queue: " << constraint_queue.size() <<
" / "
216 int num_detected = 0;
217 double max_scaling = 0.0;
218 auto scale_and_mark_as_integer = [&](
int var,
double scaling)
mutable {
220 CHECK(!mp_model->variable(
var).is_integer());
221 CHECK_EQ(var_scaling[
var], 1.0);
222 VLOG_IF(2, scaling != 1.0) <<
"Scaled " <<
var <<
" by " << scaling;
225 max_scaling =
std::max(max_scaling, scaling);
229 var_scaling[
var] = scaling;
230 mp_model->mutable_variable(
var)->set_is_integer(
true);
233 for (
const int ct_index : var_to_constraints[
var]) {
234 constraint_to_num_non_integer[ct_index]--;
235 if (constraint_to_num_non_integer[ct_index] == 1) {
236 constraint_queue.push_back(ct_index);
241 int num_fail_due_to_rhs = 0;
242 int num_fail_due_to_large_multiplier = 0;
243 int num_processed_constraints = 0;
244 while (!constraint_queue.empty()) {
245 const int top_ct_index = constraint_queue.back();
246 constraint_queue.pop_back();
250 if (constraint_to_num_non_integer[top_ct_index] == 0)
continue;
253 const MPConstraintProto&
ct = mp_model->constraint(top_ct_index);
254 if (
ct.lower_bound() + tolerance <
ct.upper_bound())
continue;
256 ++num_processed_constraints;
268 double multiplier = 1.0;
269 const double max_multiplier = 1e4;
271 for (
int i = 0; i <
ct.var_index().size(); ++i) {
272 if (!mp_model->variable(
ct.var_index(i)).is_integer()) {
274 var =
ct.var_index(i);
275 var_coeff =
ct.coefficient(i);
280 multiplier *
ct.coefficient(i) / var_scaling[
ct.var_index(i)];
283 if (multiplier == 0 || multiplier > max_multiplier) {
289 if (multiplier == 0 || multiplier > max_multiplier) {
290 ++num_fail_due_to_large_multiplier;
295 const double rhs =
ct.lower_bound();
296 if (std::abs(std::round(rhs * multiplier) - rhs * multiplier) >
297 tolerance * multiplier) {
298 ++num_fail_due_to_rhs;
308 double best_scaling = std::abs(var_coeff * multiplier);
309 for (
const int ct_index : var_to_constraints[
var]) {
310 if (ct_index == top_ct_index)
continue;
311 if (constraint_to_num_non_integer[ct_index] != 1)
continue;
314 const MPConstraintProto&
ct = mp_model->constraint(top_ct_index);
315 if (
ct.lower_bound() + tolerance <
ct.upper_bound())
continue;
317 const double multiplier = GetIntegralityMultiplier(
318 *mp_model, var_scaling,
var, ct_index, tolerance);
319 if (multiplier != 0.0 && multiplier < best_scaling) {
320 best_scaling = multiplier;
324 scale_and_mark_as_integer(
var, best_scaling);
332 int num_in_inequalities = 0;
333 int num_to_be_handled = 0;
334 for (
int var = 0;
var < num_variables; ++
var) {
335 if (mp_model->variable(
var).is_integer())
continue;
338 if (var_to_constraints[
var].empty())
continue;
341 for (
const int ct_index : var_to_constraints[
var]) {
342 if (constraint_to_num_non_integer[ct_index] != 1) {
349 std::vector<double> scaled_coeffs;
350 for (
const int ct_index : var_to_constraints[
var]) {
351 const double multiplier = GetIntegralityMultiplier(
352 *mp_model, var_scaling,
var, ct_index, tolerance);
353 if (multiplier == 0.0) {
357 scaled_coeffs.push_back(multiplier);
366 double scaling = scaled_coeffs[0];
367 for (
const double c : scaled_coeffs) {
370 CHECK_GT(scaling, 0.0);
371 for (
const double c : scaled_coeffs) {
372 const double fraction = c / scaling;
373 if (std::abs(std::round(fraction) - fraction) > tolerance) {
385 for (
const double bound : {mp_model->variable(
var).lower_bound(),
386 mp_model->variable(
var).upper_bound()}) {
387 if (!std::isfinite(
bound))
continue;
388 if (std::abs(std::round(
bound * scaling) -
bound * scaling) >
389 tolerance * scaling) {
401 ++num_in_inequalities;
402 scale_and_mark_as_integer(
var, scaling);
404 VLOG(1) <<
"num_new_integer: " << num_detected
405 <<
" num_processed_constraints: " << num_processed_constraints
406 <<
" num_rhs_fail: " << num_fail_due_to_rhs
407 <<
" num_multiplier_fail: " << num_fail_due_to_large_multiplier;
409 if (log_info && num_to_be_handled > 0) {
410 LOG(INFO) <<
"Missed " << num_to_be_handled
411 <<
" potential implied integer.";
414 const int num_integers = initial_num_integers + num_detected;
415 LOG_IF(INFO, log_info) <<
"Num integers: " << num_integers <<
"/"
416 << num_variables <<
" (implied: " << num_detected
417 <<
" in_inequalities: " << num_in_inequalities
418 <<
" max_scaling: " << max_scaling <<
")"
419 << (num_integers == num_variables ?
" [IP] "
422 ApplyVarScaling(var_scaling, mp_model);
429 struct ConstraintScaler {
431 ConstraintProto* AddConstraint(
const MPModelProto& mp_model,
432 const MPConstraintProto& mp_constraint,
433 CpModelProto* cp_model);
449 double FindFractionalScaling(
const std::vector<double>&
coefficients,
451 double multiplier = 1.0;
455 if (multiplier == 0.0)
break;
462 ConstraintProto* ConstraintScaler::AddConstraint(
463 const MPModelProto& mp_model,
const MPConstraintProto& mp_constraint,
464 CpModelProto* cp_model) {
465 if (mp_constraint.lower_bound() == -
kInfinity &&
466 mp_constraint.upper_bound() ==
kInfinity) {
470 auto* constraint = cp_model->add_constraints();
471 constraint->set_name(mp_constraint.name());
472 auto* arg = constraint->mutable_linear();
480 double ct_norm = 0.0;
488 const int num_coeffs = mp_constraint.coefficient_size();
489 for (
int i = 0; i < num_coeffs; ++i) {
490 const auto& var_proto = cp_model->variables(mp_constraint.var_index(i));
491 const int64 lb = var_proto.domain(0);
492 const int64 ub = var_proto.domain(var_proto.domain_size() - 1);
493 if (lb == 0 && ub == 0)
continue;
495 const double coeff = mp_constraint.coefficient(i);
496 if (coeff == 0.0)
continue;
498 ct_norm += coeff * coeff;
504 ct_norm =
std::max(1.0, std::sqrt(ct_norm));
509 if (lb > 1.0) ct_norm =
std::max(ct_norm, lb);
510 if (ub < -1.0) ct_norm =
std::max(ct_norm, -ub);
520 double x =
std::min(scaling_factor, 1.0);
521 double relative_coeff_error;
522 double scaled_sum_error;
523 for (; x <= scaling_factor; x *= 2) {
525 &relative_coeff_error, &scaled_sum_error);
535 const double integer_factor = FindFractionalScaling(
coefficients, 1e-8);
536 if (integer_factor != 0 && integer_factor < scaling_factor) {
538 &relative_coeff_error, &scaled_sum_error);
540 scaling_factor = integer_factor;
551 bool relax_bound = scaled_sum_error > 0;
554 const double scaled_value =
coefficients[i] * scaling_factor;
555 const int64 value =
static_cast<int64>(std::round(scaled_value)) / gcd;
557 if (!mp_model.variable(
var_indices[i]).is_integer()) {
561 arg->add_coeffs(
value);
573 const Fractional scaled_lb = std::ceil(lb * scaling_factor);
577 arg->add_domain(
CeilRatio(IntegerValue(
static_cast<int64>(scaled_lb)),
585 const Fractional scaled_ub = std::floor(ub * scaling_factor);
589 arg->add_domain(
FloorRatio(IntegerValue(
static_cast<int64>(scaled_ub)),
600 const MPModelProto& mp_model,
601 CpModelProto* cp_model) {
602 CHECK(cp_model !=
nullptr);
604 cp_model->set_name(mp_model.name());
618 const int64 kMaxVariableBound =
static_cast<int64>(params.mip_max_bound());
620 int num_truncated_bounds = 0;
621 int num_small_domains = 0;
622 const int64 kSmallDomainSize = 1000;
623 const double kWantedPrecision = params.mip_wanted_precision();
626 const int num_variables = mp_model.variable_size();
627 for (
int i = 0; i < num_variables; ++i) {
628 const MPVariableProto& mp_var = mp_model.variable(i);
629 IntegerVariableProto* cp_var = cp_model->add_variables();
630 cp_var->set_name(mp_var.name());
637 if (mp_var.lower_bound() > kMaxVariableBound) {
639 ++num_truncated_bounds;
640 const int64 value =
static_cast<int64>(std::round(mp_var.lower_bound()));
641 cp_var->add_domain(
value);
642 cp_var->add_domain(
value);
644 }
else if (mp_var.upper_bound() < -kMaxVariableBound) {
646 ++num_truncated_bounds;
647 const int64 value =
static_cast<int64>(std::round(mp_var.upper_bound()));
648 cp_var->add_domain(
value);
649 cp_var->add_domain(
value);
654 for (
const bool lower : {
true,
false}) {
655 const double bound = lower ? mp_var.lower_bound() : mp_var.upper_bound();
656 if (std::abs(
bound) >= kMaxVariableBound) {
657 ++num_truncated_bounds;
658 cp_var->add_domain(
bound < 0 ? -kMaxVariableBound : kMaxVariableBound);
664 static_cast<int64>(lower ? std::ceil(
bound - kWantedPrecision)
665 : std::floor(
bound + kWantedPrecision)));
668 if (cp_var->domain(0) > cp_var->domain(1)) {
669 LOG(WARNING) <<
"Variable #" << i <<
" cannot take integer value. "
670 << mp_var.ShortDebugString();
676 if (!mp_var.is_integer() && cp_var->domain(0) != cp_var->domain(1) &&
677 cp_var->domain(1) - cp_var->domain(0) < kSmallDomainSize) {
682 LOG_IF(WARNING, num_truncated_bounds > 0)
683 << num_truncated_bounds <<
" bounds were truncated to "
684 << kMaxVariableBound <<
".";
685 LOG_IF(WARNING, num_small_domains > 0)
686 << num_small_domains <<
" continuous variable domain with fewer than "
687 << kSmallDomainSize <<
" values.";
689 ConstraintScaler scaler;
690 const int64 kScalingTarget =
int64{1} << params.mip_max_activity_exponent();
691 scaler.wanted_precision = kWantedPrecision;
692 scaler.scaling_target = kScalingTarget;
695 for (
const MPConstraintProto& mp_constraint : mp_model.constraint()) {
696 scaler.AddConstraint(mp_model, mp_constraint, cp_model);
698 for (
const MPGeneralConstraintProto& general_constraint :
699 mp_model.general_constraint()) {
700 switch (general_constraint.general_constraint_case()) {
701 case MPGeneralConstraintProto::kIndicatorConstraint: {
702 const auto& indicator_constraint =
703 general_constraint.indicator_constraint();
704 const MPConstraintProto& mp_constraint =
705 indicator_constraint.constraint();
706 ConstraintProto*
ct =
707 scaler.AddConstraint(mp_model, mp_constraint, cp_model);
708 if (
ct ==
nullptr)
continue;
711 const int var = indicator_constraint.var_index();
712 const int value = indicator_constraint.var_value();
716 case MPGeneralConstraintProto::kAndConstraint: {
717 const auto& and_constraint = general_constraint.and_constraint();
718 const std::string&
name = general_constraint.name();
720 ConstraintProto* ct_pos = cp_model->add_constraints();
721 ct_pos->set_name(
name.empty() ?
"" : absl::StrCat(
name,
"_pos"));
722 ct_pos->add_enforcement_literal(and_constraint.resultant_var_index());
723 *ct_pos->mutable_bool_and()->mutable_literals() =
724 and_constraint.var_index();
726 ConstraintProto* ct_neg = cp_model->add_constraints();
727 ct_neg->set_name(
name.empty() ?
"" : absl::StrCat(
name,
"_neg"));
728 ct_neg->add_enforcement_literal(
729 NegatedRef(and_constraint.resultant_var_index()));
730 for (
const int var_index : and_constraint.var_index()) {
731 ct_neg->mutable_bool_or()->add_literals(
NegatedRef(var_index));
735 case MPGeneralConstraintProto::kOrConstraint: {
736 const auto& or_constraint = general_constraint.or_constraint();
737 const std::string&
name = general_constraint.name();
739 ConstraintProto* ct_pos = cp_model->add_constraints();
740 ct_pos->set_name(
name.empty() ?
"" : absl::StrCat(
name,
"_pos"));
741 ct_pos->add_enforcement_literal(or_constraint.resultant_var_index());
742 *ct_pos->mutable_bool_or()->mutable_literals() =
743 or_constraint.var_index();
745 ConstraintProto* ct_neg = cp_model->add_constraints();
746 ct_neg->set_name(
name.empty() ?
"" : absl::StrCat(
name,
"_neg"));
747 ct_neg->add_enforcement_literal(
748 NegatedRef(or_constraint.resultant_var_index()));
749 for (
const int var_index : or_constraint.var_index()) {
750 ct_neg->mutable_bool_and()->add_literals(
NegatedRef(var_index));
755 LOG(ERROR) <<
"Can't convert general constraints of type "
756 << general_constraint.general_constraint_case()
757 <<
" to CpModelProto.";
767 VLOG(1) <<
"Maximum constraint coefficient relative error: "
769 VLOG(1) <<
"Maximum constraint worst-case sum error: " <<
max_sum_error;
777 for (
int i = 0; i < num_variables; ++i) {
778 const MPVariableProto& mp_var = mp_model.variable(i);
779 if (mp_var.objective_coefficient() == 0.0)
continue;
781 const auto& var_proto = cp_model->variables(i);
782 const int64 lb = var_proto.domain(0);
783 const int64 ub = var_proto.domain(var_proto.domain_size() - 1);
784 if (lb == 0 && ub == 0)
continue;
791 if (!
coefficients.empty() || mp_model.objective_offset() != 0.0) {
800 double x =
std::min(scaling_factor, 1.0);
801 double relative_coeff_error;
802 double scaled_sum_error;
803 for (; x <= scaling_factor; x *= 2) {
805 &relative_coeff_error, &scaled_sum_error);
806 if (scaled_sum_error < kWantedPrecision * x)
break;
812 const double integer_factor = FindFractionalScaling(
coefficients, 1e-8);
813 if (integer_factor != 0 && integer_factor < scaling_factor) {
815 &relative_coeff_error, &scaled_sum_error);
816 if (scaled_sum_error < kWantedPrecision * integer_factor) {
817 scaling_factor = integer_factor;
826 VLOG(1) <<
"objective coefficient relative error: " << relative_coeff_error;
827 VLOG(1) <<
"objective worst-case absolute error: "
828 << scaled_sum_error / scaling_factor;
829 VLOG(1) <<
"objective scaling factor: " << scaling_factor / gcd;
834 auto* objective = cp_model->mutable_objective();
835 const int mult = mp_model.maximize() ? -1 : 1;
836 objective->set_offset(mp_model.objective_offset() * scaling_factor / gcd *
838 objective->set_scaling_factor(1.0 / scaling_factor * gcd * mult);
845 objective->add_coeffs(
value * mult);
851 const double allowed_error =
852 std::max(params.mip_check_precision(), params.mip_wanted_precision());
854 LOG(WARNING) <<
"The relative error during double -> int64 conversion "
856 <<
" check_tolerance:" << allowed_error;
863 LinearBooleanProblem* problem) {
864 CHECK(problem !=
nullptr);
866 problem->set_name(mp_model.name());
867 const int num_variables = mp_model.variable_size();
868 problem->set_num_variables(num_variables);
872 for (
int var_id(0); var_id < num_variables; ++var_id) {
873 const MPVariableProto& mp_var = mp_model.variable(var_id);
874 problem->add_var_names(mp_var.name());
879 bool is_binary = mp_var.is_integer();
883 if (lb <= -1.0) is_binary =
false;
884 if (ub >= 2.0) is_binary =
false;
887 if (lb <= 0.0 && ub >= 1.0) {
889 }
else if (lb <= 1.0 && ub >= 1.0) {
891 LinearBooleanConstraint* constraint = problem->add_constraints();
892 constraint->set_lower_bound(1);
893 constraint->set_upper_bound(1);
894 constraint->add_literals(var_id + 1);
895 constraint->add_coefficients(1);
896 }
else if (lb <= 0.0 && ub >= 0.0) {
898 LinearBooleanConstraint* constraint = problem->add_constraints();
899 constraint->set_lower_bound(0);
900 constraint->set_upper_bound(0);
901 constraint->add_literals(var_id + 1);
902 constraint->add_coefficients(1);
911 LOG(WARNING) <<
"The variable #" << var_id <<
" with name "
912 << mp_var.name() <<
" is not binary. "
913 <<
"lb: " << lb <<
" ub: " << ub;
920 double max_relative_error = 0.0;
921 double max_bound_error = 0.0;
923 double relative_error = 0.0;
924 double scaling_factor = 0.0;
928 for (
const MPConstraintProto& mp_constraint : mp_model.constraint()) {
929 LinearBooleanConstraint* constraint = problem->add_constraints();
930 constraint->set_name(mp_constraint.name());
934 const int num_coeffs = mp_constraint.coefficient_size();
935 for (
int i = 0; i < num_coeffs; ++i) {
941 max_relative_error =
std::max(relative_error, max_relative_error);
944 double bound_error = 0.0;
945 for (
int i = 0; i < num_coeffs; ++i) {
946 const double scaled_value = mp_constraint.coefficient(i) * scaling_factor;
947 bound_error += std::abs(round(scaled_value) - scaled_value);
950 constraint->add_literals(mp_constraint.var_index(i) + 1);
951 constraint->add_coefficients(
value);
954 max_bound_error =
std::max(max_bound_error, bound_error);
961 const Fractional lb = mp_constraint.lower_bound();
963 if (lb * scaling_factor >
static_cast<double>(kInt64Max)) {
964 LOG(WARNING) <<
"A constraint is trivially unsatisfiable.";
967 if (lb * scaling_factor > -
static_cast<double>(kInt64Max)) {
969 constraint->set_lower_bound(
970 static_cast<int64>(round(lb * scaling_factor - bound_error)) / gcd);
973 const Fractional ub = mp_constraint.upper_bound();
975 if (ub * scaling_factor < -
static_cast<double>(kInt64Max)) {
976 LOG(WARNING) <<
"A constraint is trivially unsatisfiable.";
979 if (ub * scaling_factor <
static_cast<double>(kInt64Max)) {
981 constraint->set_upper_bound(
982 static_cast<int64>(round(ub * scaling_factor + bound_error)) / gcd);
988 LOG(INFO) <<
"Maximum constraint relative error: " << max_relative_error;
989 LOG(INFO) <<
"Maximum constraint bound error: " << max_bound_error;
994 for (
int var_id = 0; var_id < num_variables; ++var_id) {
995 const MPVariableProto& mp_var = mp_model.variable(var_id);
1001 max_relative_error =
std::max(relative_error, max_relative_error);
1004 LOG(INFO) <<
"objective relative error: " << relative_error;
1005 LOG(INFO) <<
"objective scaling factor: " << scaling_factor / gcd;
1007 LinearObjective* objective = problem->mutable_objective();
1008 objective->set_offset(mp_model.objective_offset() * scaling_factor / gcd);
1012 objective->set_scaling_factor(1.0 / scaling_factor * gcd);
1013 for (
int var_id = 0; var_id < num_variables; ++var_id) {
1014 const MPVariableProto& mp_var = mp_model.variable(var_id);
1016 mp_var.objective_coefficient() * scaling_factor)) /
1019 objective->add_literals(var_id + 1);
1020 objective->add_coefficients(
value);
1028 const double kRelativeTolerance = 1e-8;
1029 if (max_relative_error > kRelativeTolerance) {
1030 LOG(WARNING) <<
"The relative error during double -> int64 conversion "
1040 for (
int i = 0; i < problem.num_variables(); ++i) {
1047 if (problem.var_names_size() != 0) {
1048 CHECK_EQ(problem.var_names_size(), problem.num_variables());
1049 for (
int i = 0; i < problem.num_variables(); ++i) {
1054 for (
const LinearBooleanConstraint& constraint : problem.constraints()) {
1058 for (
int i = 0; i < constraint.literals_size(); ++i) {
1059 const int literal = constraint.literals(i);
1060 const double coeff = constraint.coefficients(i);
1061 const ColIndex variable_index = ColIndex(abs(
literal) - 1);
1071 constraint.has_lower_bound() ? constraint.lower_bound() - sum
1073 constraint.has_upper_bound() ? constraint.upper_bound() - sum
1080 const LinearObjective& objective = problem.objective();
1081 const double scaling_factor = objective.scaling_factor();
1082 for (
int i = 0; i < objective.literals_size(); ++i) {
1083 const int literal = objective.literals(i);
1084 const double coeff =
1085 static_cast<double>(objective.coefficients(i)) * scaling_factor;
1086 const ColIndex variable_index = ColIndex(abs(
literal) - 1);
1102 int num_fixed_variables = 0;
1104 for (
int i = 0; i < trail.
Index(); ++i) {
1105 const BooleanVariable
var = trail[i].Variable();
1106 const int value = trail[i].IsPositive() ? 1.0 : 0.0;
1108 ++num_fixed_variables;
1112 return num_fixed_variables;
1117 double max_time_in_seconds) {
1119 glop::GlopParameters glop_parameters;
1120 glop_parameters.set_max_time_in_seconds(max_time_in_seconds);
1125 status != glop::ProblemStatus::PRIMAL_FEASIBLE) {
1138 LinearBooleanProblem* problem) {
1142 status != glop::ProblemStatus::PRIMAL_FEASIBLE)
1144 int num_variable_fixed = 0;
1148 if (
value > 1 - tolerance) {
1149 ++num_variable_fixed;
1150 LinearBooleanConstraint* constraint = problem->add_constraints();
1151 constraint->set_lower_bound(1);
1152 constraint->set_upper_bound(1);
1153 constraint->add_coefficients(1);
1154 constraint->add_literals(
col.value() + 1);
1155 }
else if (
value < tolerance) {
1156 ++num_variable_fixed;
1157 LinearBooleanConstraint* constraint = problem->add_constraints();
1158 constraint->set_lower_bound(0);
1159 constraint->set_upper_bound(0);
1160 constraint->add_coefficients(1);
1161 constraint->add_literals(
col.value() + 1);
1164 LOG(INFO) <<
"LNS with " << num_variable_fixed <<
" fixed variables.";