cleanup cuts code
This commit is contained in:
@@ -24,12 +24,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "glog/vlog_is_on.h"
|
||||
#include "ortools/sat/cuts.h"
|
||||
#include "ortools/sat/sat_parameters.pb.h"
|
||||
#include "ortools/util/saturated_arithmetic.h"
|
||||
|
||||
#if !defined(__PORTABLE_PLATFORM__)
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
@@ -37,10 +31,12 @@
|
||||
#endif // __PORTABLE_PLATFORM__
|
||||
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "glog/vlog_is_on.h"
|
||||
#include "ortools/base/cleanup.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/int_type.h"
|
||||
@@ -63,6 +59,7 @@
|
||||
#include "ortools/sat/cp_model_presolve.h"
|
||||
#include "ortools/sat/cp_model_search.h"
|
||||
#include "ortools/sat/cp_model_utils.h"
|
||||
#include "ortools/sat/cuts.h"
|
||||
#include "ortools/sat/drat_checker.h"
|
||||
#include "ortools/sat/drat_proof_handler.h"
|
||||
#include "ortools/sat/integer.h"
|
||||
@@ -76,6 +73,7 @@
|
||||
#include "ortools/sat/probing.h"
|
||||
#include "ortools/sat/rins.h"
|
||||
#include "ortools/sat/sat_base.h"
|
||||
#include "ortools/sat/sat_parameters.pb.h"
|
||||
#include "ortools/sat/sat_solver.h"
|
||||
#include "ortools/sat/simplification.h"
|
||||
#include "ortools/sat/synchronization.h"
|
||||
|
||||
@@ -809,23 +809,21 @@ CutGenerator CreatePositiveMultiplicationCutGenerator(IntegerVariable z,
|
||||
return;
|
||||
}
|
||||
|
||||
const double x_value = lp_values[x];
|
||||
const double y_value = lp_values[y];
|
||||
const double z_value = lp_values[z];
|
||||
const double x_lp_value = lp_values[x];
|
||||
const double y_lp_value = lp_values[y];
|
||||
const double z_lp_value = lp_values[z];
|
||||
|
||||
// TODO: As the bounds change monotonically, these cuts dominate any
|
||||
// previous one. try to keep a reference to the cut and replace it.
|
||||
// Alternatively, add an API for a level-zero bound change callback.
|
||||
|
||||
// We implement the McCormick relaxation of bilinear constraints.
|
||||
// TODO(user): As the bounds change monotonically, these cuts
|
||||
// dominate any previous one. try to keep a reference to the cut and
|
||||
// replace it. Alternatively, add an API for a level-zero bound change
|
||||
// callback.
|
||||
|
||||
// Cut -z + x_coeff * x + y_coeff* y <= rhs
|
||||
auto try_add_above_cut = [manager, z_value, x_value, y_value, x, y, z,
|
||||
lp_values](int64 x_coeff, int64 y_coeff,
|
||||
int64 rhs) {
|
||||
if (-z_value + x_value * x_coeff + y_value * y_coeff >=
|
||||
auto try_add_above_cut = [manager, z_lp_value, x_lp_value, y_lp_value,
|
||||
x, y, z, lp_values](
|
||||
int64 x_coeff, int64 y_coeff, int64 rhs) {
|
||||
if (-z_lp_value + x_lp_value * x_coeff + y_lp_value * y_coeff >=
|
||||
rhs + kMinCutViolation) {
|
||||
// cut: -z + x * x_coeff + y * y_coeff <= rhs
|
||||
LinearConstraint cut;
|
||||
cut.vars.push_back(z);
|
||||
cut.coeffs.push_back(IntegerValue(-1));
|
||||
@@ -844,12 +842,11 @@ CutGenerator CreatePositiveMultiplicationCutGenerator(IntegerVariable z,
|
||||
};
|
||||
|
||||
// Cut -z + x_coeff * x + y_coeff* y >= rhs
|
||||
auto try_add_below_cut = [manager, z_value, x_value, y_value, x, y, z,
|
||||
lp_values](int64 x_coeff, int64 y_coeff,
|
||||
int64 rhs) {
|
||||
if (-z_value + x_value * x_coeff + y_value * y_coeff <=
|
||||
auto try_add_below_cut = [manager, z_lp_value, x_lp_value, y_lp_value,
|
||||
x, y, z, lp_values](
|
||||
int64 x_coeff, int64 y_coeff, int64 rhs) {
|
||||
if (-z_lp_value + x_lp_value * x_coeff + y_lp_value * y_coeff <=
|
||||
rhs - kMinCutViolation) {
|
||||
// cut: -z + x * x_coeff + y * y_coeff >= rhs
|
||||
LinearConstraint cut;
|
||||
cut.vars.push_back(z);
|
||||
cut.coeffs.push_back(IntegerValue(-1));
|
||||
@@ -867,10 +864,15 @@ CutGenerator CreatePositiveMultiplicationCutGenerator(IntegerVariable z,
|
||||
}
|
||||
};
|
||||
|
||||
// McCormick cuts.
|
||||
// McCormick relaxation of bilinear constraints. These 4 cuts are the
|
||||
// exact facets of the x * y polyhedron for a bounded x and y.
|
||||
//
|
||||
// Each cut correspond to plane that contains two of the line
|
||||
// (x=x_lb), (x=x_ub), (y=y_lb), (y=y_ub). The easiest to
|
||||
// understand them is to draw the x*y curves and see the 4
|
||||
// planes that correspond to the convex hull of the graph.
|
||||
try_add_above_cut(y_lb, x_lb, x_lb * y_lb);
|
||||
try_add_above_cut(y_ub, x_ub, x_ub * y_ub);
|
||||
|
||||
try_add_below_cut(y_ub, x_lb, x_lb * y_ub);
|
||||
try_add_below_cut(y_lb, x_ub, x_ub * y_lb);
|
||||
};
|
||||
@@ -885,7 +887,7 @@ CutGenerator CreateSquareCutGenerator(IntegerVariable y, IntegerVariable x,
|
||||
|
||||
IntegerTrail* integer_trail = model->GetOrCreate<IntegerTrail>();
|
||||
result.generate_cuts =
|
||||
[y, x, model, integer_trail](
|
||||
[y, x, integer_trail](
|
||||
const gtl::ITIVector<IntegerVariable, double>& lp_values,
|
||||
LinearConstraintManager* manager) {
|
||||
const int64 x_ub = integer_trail->LevelZeroUpperBound(x).value();
|
||||
@@ -894,14 +896,14 @@ CutGenerator CreateSquareCutGenerator(IntegerVariable y, IntegerVariable x,
|
||||
if (x_lb == x_ub) return;
|
||||
|
||||
// Check for potential overflows.
|
||||
if (x_ub > int64{1000000000}) return;
|
||||
if (x_ub > (int64{1} << 31)) return;
|
||||
DCHECK_GE(x_lb, 0);
|
||||
|
||||
const double y_value = lp_values[y];
|
||||
const double x_value = lp_values[x];
|
||||
|
||||
// First cut: target should be below the line:
|
||||
// (x_lb, val_lb ^ 2) to (x_ub, x_ub ^ 2).
|
||||
// (x_lb, x_lb ^ 2) to (x_ub, x_ub ^ 2).
|
||||
// The slope of that line is (ub^2 - lb^2) / (ub - lb) = ub + lb.
|
||||
const int64 y_lb = x_lb * x_lb;
|
||||
const int64 above_slope = x_ub + x_lb;
|
||||
@@ -921,14 +923,16 @@ CutGenerator CreateSquareCutGenerator(IntegerVariable y, IntegerVariable x,
|
||||
// Second cut: target should be above all the lines
|
||||
// (value, value ^ 2) to (value + 1, (value + 1) ^ 2)
|
||||
// The slope of that line is 2 * value + 1
|
||||
//
|
||||
// Note that we only add one of these cuts. The one for x_lp_value in
|
||||
// [value, value + 1].
|
||||
const int64 x_floor = static_cast<int64>(std::floor(x_value));
|
||||
const int64 below_slope = 2 * x_floor + 1;
|
||||
const double min_y =
|
||||
below_slope * x_value - x_floor - x_floor * x_floor;
|
||||
if (min_y >= y_value + kMinCutViolation) {
|
||||
// cut: target >= below_slope * (x - x_floor) +
|
||||
// x_floor * x_floor
|
||||
// : target >= below_slope * x - x_floor ^ 2 - x_floor
|
||||
// cut: y >= below_slope * (x - x_floor) + x_floor ^ 2
|
||||
// : y >= below_slope * x - x_floor ^ 2 - x_floor
|
||||
LinearConstraint below_cut;
|
||||
below_cut.vars.push_back(y);
|
||||
below_cut.coeffs.push_back(IntegerValue(1));
|
||||
|
||||
@@ -255,13 +255,13 @@ CutGenerator CreateKnapsackCoverCutGenerator(
|
||||
const std::vector<LinearConstraint>& base_constraints,
|
||||
const std::vector<IntegerVariable>& vars, Model* model);
|
||||
|
||||
// A cut generator for z = x * y (x and y >= 0)
|
||||
// A cut generator for z = x * y (x and y >= 0).
|
||||
CutGenerator CreatePositiveMultiplicationCutGenerator(IntegerVariable z,
|
||||
IntegerVariable x,
|
||||
IntegerVariable y,
|
||||
Model* model);
|
||||
|
||||
// A cut generator for y = x ^ 2. (x >= 0).
|
||||
// A cut generator for y = x ^ 2 (x >= 0).
|
||||
// It will dynamically add a linear inequality to push y closer to the parabola.
|
||||
CutGenerator CreateSquareCutGenerator(IntegerVariable y, IntegerVariable x,
|
||||
Model* model);
|
||||
|
||||
Reference in New Issue
Block a user