89 absl::Span<const Variable> variables,
95 const ModelProto model_proto =
model.ExportModel();
102 "MoveVariablesToTheirBestFeasibleValue"));
104 for (
const Variable v : variables) {
106 <<
"invalid `variables`";
107 if (v.lower_bound() > v.upper_bound()) {
109 <<
"variable " << v <<
" bounds ["
112 <<
"] integer: " << std::boolalpha << v.is_integer()
118 <<
"integer variable " << v <<
" has bounds ["
121 <<
"] that contain no integer value";
125 <<
"invalid `input_solution`";
139 constraint_values.try_emplace(
c, ConstraintValue(
c, new_solution));
141 for (
const Variable v : variables) {
142 const double obj_coeff =
model.objective_coefficient(v);
145 if (obj_coeff == 0.0)
continue;
147 const double v_current_value = new_solution.at(v);
154 const bool positive_v_change =
model.is_maximize() == (obj_coeff > 0.0);
158 double best_v_bound =
168 bool some_constraints_are_limiting =
false;
172 CHECK(std::isfinite(c_coeff)) << v <<
": " << c_coeff;
175 if (c_coeff == 0.0)
continue;
179 const bool use_constraint_upper_bound =
180 (c_coeff >= 0.0) == positive_v_change;
183 const double used_bound =
185 if (!std::isfinite(used_bound))
continue;
188 some_constraints_are_limiting =
true;
191 const double c_v_bound = [&]() {
192 const double c_value = constraint_values.at(
c);
200 if (!std::isfinite(c_value))
return v_current_value;
208 if ((c_value >= used_bound) == use_constraint_upper_bound) {
209 return v_current_value;
212 return v_current_value + ((used_bound - c_value) / c_coeff);
216 if (positive_v_change) {
217 best_v_bound = std::fmin(best_v_bound, c_v_bound);
219 best_v_bound = std::fmax(best_v_bound, c_v_bound);
223 if (!std::isfinite(best_v_bound)) {
224 if (some_constraints_are_limiting) {
236 <<
"the model is unbounded regarding variable " << v;
239 const double v_improved_value = [&]() {
240 if (!v.is_integer()) {
247 return positive_v_change ? std::floor(best_v_bound)
248 : std::ceil(best_v_bound);
252 if (positive_v_change ? v_improved_value <= v_current_value
253 : v_improved_value >= v_current_value)
259 new_solution.at(v) = v_improved_value;
267 constraint_values.at(
c) = ConstraintValue(
c, new_solution);