fix scaling issue in probing; fix overflow in feasibility pump; fix missing presolve

This commit is contained in:
Laurent Perron
2020-06-12 15:05:29 +02:00
parent 1d13bada39
commit 75403abd3f
3 changed files with 35 additions and 22 deletions

View File

@@ -478,9 +478,8 @@ void FeasibilityPump::FillIntegerSolutionStats() {
// Compute the objective value.
integer_solution_objective_ = 0;
for (const auto& term : integer_objective_) {
integer_solution_objective_ = CapAdd(
integer_solution_objective_,
CapProd(integer_solution_[term.first.value()], term.second.value()));
integer_solution_objective_ +=
integer_solution_[term.first.value()] * term.second.value();
}
integer_solution_is_feasible_ = true;

View File

@@ -117,6 +117,7 @@ struct ConstraintScaler {
double wanted_precision = 1e-6;
int64 scaling_target = int64{1} << 50;
std::vector<int> var_indices;
std::vector<double> coefficients;
std::vector<double> lower_bounds;
std::vector<double> upper_bounds;
@@ -136,15 +137,22 @@ ConstraintProto* ConstraintScaler::AddConstraint(
// First scale the coefficients of the constraints so that the constraint
// sum can always be computed without integer overflow.
var_indices.clear();
coefficients.clear();
lower_bounds.clear();
upper_bounds.clear();
const int num_coeffs = mp_constraint.coefficient_size();
for (int i = 0; i < num_coeffs; ++i) {
coefficients.push_back(mp_constraint.coefficient(i));
const auto& var_proto = cp_model->variables(mp_constraint.var_index(i));
lower_bounds.push_back(var_proto.domain(0));
upper_bounds.push_back(var_proto.domain(var_proto.domain_size() - 1));
const int64 lb = var_proto.domain(0);
const int64 ub = var_proto.domain(var_proto.domain_size() - 1);
if (lb == 0 && ub == 0) continue;
if (mp_constraint.coefficient(i) == 0.0) continue;
var_indices.push_back(mp_constraint.var_index(i));
coefficients.push_back(mp_constraint.coefficient(i));
lower_bounds.push_back(lb);
upper_bounds.push_back(ub);
}
double scaling_factor = GetBestScalingOfDoublesToInt64(
coefficients, lower_bounds, upper_bounds, scaling_target);
@@ -182,14 +190,14 @@ ConstraintProto* ConstraintScaler::AddConstraint(
// we made no error at all during our scaling.
bool relax_bound = scaled_sum_error > 0;
for (int i = 0; i < num_coeffs; ++i) {
const double scaled_value = mp_constraint.coefficient(i) * scaling_factor;
for (int i = 0; i < coefficients.size(); ++i) {
const double scaled_value = coefficients[i] * scaling_factor;
const int64 value = static_cast<int64>(std::round(scaled_value)) / gcd;
if (value != 0) {
if (!mp_model.variable(mp_constraint.var_index(i)).is_integer()) {
if (!mp_model.variable(var_indices[i]).is_integer()) {
relax_bound = true;
}
arg->add_vars(mp_constraint.var_index(i));
arg->add_vars(var_indices[i]);
arg->add_coeffs(value);
}
}
@@ -397,16 +405,23 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params,
VLOG(1) << "Maximum constraint scaling factor: " << max_scaling_factor;
// Add the objective.
std::vector<int> var_indices;
std::vector<double> coefficients;
std::vector<double> lower_bounds;
std::vector<double> upper_bounds;
for (int i = 0; i < num_variables; ++i) {
const MPVariableProto& mp_var = mp_model.variable(i);
if (mp_var.objective_coefficient() == 0.0) continue;
coefficients.push_back(mp_var.objective_coefficient());
const auto& var_proto = cp_model->variables(i);
lower_bounds.push_back(var_proto.domain(0));
upper_bounds.push_back(var_proto.domain(var_proto.domain_size() - 1));
const int64 lb = var_proto.domain(0);
const int64 ub = var_proto.domain(var_proto.domain_size() - 1);
if (lb == 0 && ub == 0) continue;
var_indices.push_back(i);
coefficients.push_back(mp_var.objective_coefficient());
lower_bounds.push_back(lb);
upper_bounds.push_back(ub);
}
if (!coefficients.empty() || mp_model.objective_offset() != 0.0) {
double scaling_factor = GetBestScalingOfDoublesToInt64(
@@ -445,14 +460,12 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params,
objective->set_offset(mp_model.objective_offset() * scaling_factor / gcd *
mult);
objective->set_scaling_factor(1.0 / scaling_factor * gcd * mult);
for (int i = 0; i < num_variables; ++i) {
const MPVariableProto& mp_var = mp_model.variable(i);
for (int i = 0; i < coefficients.size(); ++i) {
const int64 value =
static_cast<int64>(
std::round(mp_var.objective_coefficient() * scaling_factor)) /
static_cast<int64>(std::round(coefficients[i] * scaling_factor)) /
gcd;
if (value != 0) {
objective->add_vars(i);
objective->add_vars(var_indices[i]);
objective->add_coeffs(value * mult);
}
}

View File

@@ -179,11 +179,11 @@ bool ProbeBooleanVariables(const double deterministic_time_limit,
IntegerValue ub_min = kMaxIntegerValue;
new_integer_bounds.push_back(IntegerLiteral()); // Sentinel.
for (int i = 1; i < new_integer_bounds.size(); ++i) {
for (int i = 0; i < new_integer_bounds.size(); ++i) {
const IntegerVariable var = new_integer_bounds[i].var;
// Hole detection.
if (PositiveVariable(var) != prev_var) {
if (i > 0 && PositiveVariable(var) != prev_var) {
if (ub_min + 1 < lb_max) {
// The variable cannot take value in (ub_min, lb_max) !
//
@@ -202,10 +202,11 @@ bool ProbeBooleanVariables(const double deterministic_time_limit,
}
// Reinitialize.
prev_var = PositiveVariable(var);
lb_max = kMinIntegerValue;
ub_min = kMaxIntegerValue;
}
prev_var = PositiveVariable(var);
if (VariableIsPositive(var)) {
lb_max = std::max(lb_max, new_integer_bounds[i].bound);
} else {
@@ -213,7 +214,7 @@ bool ProbeBooleanVariables(const double deterministic_time_limit,
}
// Bound tightening.
if (new_integer_bounds[i - 1].var != var) continue;
if (i == 0 || new_integer_bounds[i - 1].var != var) continue;
const IntegerValue new_bound = std::min(new_integer_bounds[i - 1].bound,
new_integer_bounds[i].bound);
if (new_bound > integer_trail->LowerBound(var)) {