14#ifndef OR_TOOLS_SAT_CUTS_H_
15#define OR_TOOLS_SAT_CUTS_H_
27#include "absl/container/btree_map.h"
28#include "absl/container/btree_set.h"
29#include "absl/container/flat_hash_map.h"
30#include "absl/container/flat_hash_set.h"
31#include "absl/numeric/int128.h"
32#include "absl/strings/str_cat.h"
33#include "absl/types/span.h"
55 std::vector<IntegerVariable>
vars;
90 IntegerValue
coeff = IntegerValue(0);
119 absl::Span<const IntegerVariable> vars,
120 absl::Span<const IntegerValue> coeffs,
121 absl::Span<const double> lp_values,
125 bool AppendOneTerm(IntegerVariable
var, IntegerValue coeff,
double lp_value,
126 IntegerValue lb, IntegerValue ub);
167 void RegisterAllBooleanTerms(
const CutData& cut);
170 bool constraint_is_indexed_ =
false;
171 absl::flat_hash_map<IntegerVariable, int> bool_index_;
172 absl::flat_hash_map<IntegerVariable, int> secondary_bool_index_;
173 absl::btree_map<IntegerVariable, IntegerValue> tmp_map_;
189 : lp_vars_(lp_vars_.begin(), lp_vars_.
end()),
190 integer_trail_(integer_trail),
191 implied_bounds_(implied_bounds) {}
207 IntegerValue factor_t,
CutTerm& bool_term,
217 IntegerValue factor_t,
CutTerm& bool_term,
226 const std::function<IntegerValue(IntegerValue)>& f, IntegerValue factor_t,
261 const double bool_term =
263 return var_lp_value -
static_cast<double>(lb.value()) - bool_term;
278 BestImpliedBoundInfo ComputeBestImpliedBound(
282 absl::flat_hash_set<IntegerVariable> lp_vars_;
283 mutable absl::flat_hash_map<IntegerVariable, BestImpliedBoundInfo> cache_;
287 std::vector<BestImpliedBoundInfo> cached_data_;
325IntegerValue
GetFactorT(IntegerValue rhs_remainder, IntegerValue divisor,
326 IntegerValue max_magnitude);
328 IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue t,
329 IntegerValue max_scaling);
351 IntegerValue positive_rhs, IntegerValue min_magnitude);
355std::function<IntegerValue(IntegerValue)>
357 IntegerValue scaling);
363 std::function<IntegerValue(IntegerValue)> base_f, IntegerValue period) {
364 const IntegerValue m = -base_f(-period);
365 return [m, period, base_f](IntegerValue v) {
367 const IntegerValue output_r = m + base_f(r - period);
420 std::string
Info()
const {
return absl::StrCat(
"ib_lift=", num_ib_used_); }
423 double GetScaledViolation(IntegerValue divisor, IntegerValue max_scaling,
424 IntegerValue remainder_threshold,
428 std::vector<IntegerValue> divisors_;
429 std::vector<IntegerValue> remainders_;
430 std::vector<IntegerValue> rs_;
431 std::vector<IntegerValue> best_rs_;
433 int64_t num_ib_used_ = 0;
437 std::vector<std::pair<int, IntegerValue>> adjusted_coeffs_;
438 std::vector<std::pair<int, IntegerValue>> best_adjusted_coeffs_;
442 int64_t total_num_dominating_f_ = 0;
443 int64_t total_num_pos_lifts_ = 0;
444 int64_t total_num_neg_lifts_ = 0;
445 int64_t total_num_post_complements_ = 0;
446 int64_t total_num_overflow_abort_ = 0;
447 int64_t total_num_coeff_adjust_ = 0;
448 int64_t total_num_merges_ = 0;
449 int64_t total_num_bumps_ = 0;
450 int64_t total_num_final_complements_ = 0;
452 int64_t total_num_initial_ibs_ = 0;
453 int64_t total_num_initial_merges_ = 0;
510 std::string
Info()
const {
return absl::StrCat(
"lift=", num_lifting_); }
517 void InitializeCut(
const CutData& input_ct);
521 template <
class CompareAdd,
class CompareRemove>
522 int GetCoverSize(
int relevant_size);
526 int GetCoverSizeForBooleans();
528 template <
class Compare>
529 int MinimizeCover(
int cover_size, absl::int128 slack);
537 bool has_bool_base_ct_ =
false;
539 int bool_cover_size_ = 0;
543 int64_t num_lifting_ = 0;
547 int64_t num_cuts = 0;
548 int64_t num_initial_ibs = 0;
549 int64_t num_lb_ibs = 0;
550 int64_t num_ub_ibs = 0;
551 int64_t num_merges = 0;
552 int64_t num_bumps = 0;
553 int64_t num_lifting = 0;
554 int64_t num_overflow_aborts = 0;
556 CutStats flow_stats_;
557 CutStats cover_stats_;
577 const absl::flat_hash_map<IntegerVariable, glop::ColIndex>& lp_vars);
586 std::string
Info()
const {
return ""; }
591 double GetLiteralLpValue(IntegerVariable
var)
const;
595 bool TryProduct(IntegerVariable factor,
const CutData&
input);
597 bool enabled_ =
false;
605 int64_t num_tried_ = 0;
606 int64_t num_tried_factors_ = 0;
613 int linearization_level,
622 AffineExpression square,
624 IntegerValue x_ub, Model*
model);
632 AffineExpression square,
633 IntegerValue x_value,
639 int linearization_level, Model*
model);
648 const std::vector<AffineExpression>& exprs, Model*
model);
688 IntegerVariable target,
const std::vector<LinearExpression>& exprs,
689 const std::vector<IntegerVariable>& z_vars, Model*
model);
695 const LinearExpression& target, IntegerVariable
var,
696 const std::vector<std::pair<IntegerValue, IntegerValue>>& affines,
697 Model*
model, LinearConstraintBuilder* builder);
704 LinearExpression target, IntegerVariable
var,
705 std::vector<std::pair<IntegerValue, IntegerValue>> affines,
706 std::string cut_name, Model*
model);
712 const std::vector<IntegerVariable>& base_variables, Model*
model);
725 int size()
const {
return expr_mins_.size(); }
728 absl::btree_set<IntegerValue> min_values_;
729 std::vector<IntegerValue> expr_mins_;
bool TrySimpleSeparation(const CutData &input_ct)
Tries RLT separation of the input constraint. Returns true on success.
BoolRLTCutHelper(Model *model)
void Initialize(const absl::flat_hash_map< IntegerVariable, glop::ColIndex > &lp_vars)
std::string Info() const
Single line of text that we append to the cut log line.
const CutData & cut() const
If successful, this contains the last generated cut.
Helper to find knapsack cover cuts.
const CutData & cut() const
If successful, info about the last generated cut.
bool TrySimpleKnapsack(const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr)
std::string Info() const
Single line of text that we append to the cut log line.
bool TryWithLetchfordSouliLifting(const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr)
void SetSharedStatistics(SharedStatistics *stats)
bool TrySingleNodeFlow(const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr)
Stores temporaries used to build or manipulate a CutData.
int NumMergesSinceLastClear() const
bool ConvertToLinearConstraint(const CutData &cut, LinearConstraint *output)
Returns false if we encounter an integer overflow.
void AddOrMergeTerm(const CutTerm &term, IntegerValue t, CutData *cut)
void RecomputeCacheAndSeparateSomeImpliedBoundCuts(const util_intops::StrongVector< IntegerVariable, double > &lp_values)
bool CacheDataForCut(IntegerVariable first_slack, CutData *cut)
ImpliedBoundsProcessor(absl::Span< const IntegerVariable > lp_vars_, IntegerTrail *integer_trail, ImpliedBounds *implied_bounds)
We will only replace IntegerVariable appearing in lp_vars_.
void AddLpVariable(IntegerVariable var)
BestImpliedBoundInfo GetCachedImpliedBoundInfo(IntegerVariable var) const
bool DecomposeWithImpliedLowerBound(const CutTerm &term, IntegerValue factor_t, CutTerm &bool_term, CutTerm &slack_term)
CutDataBuilder * BaseCutBuilder()
bool TryToExpandWithLowerImpliedbound(IntegerValue factor_t, int i, bool complement, CutData *cut, CutDataBuilder *builder)
Important: The cut_builder_ must have been reset.
std::pair< int, int > PostprocessWithImpliedBound(const std::function< IntegerValue(IntegerValue)> &f, IntegerValue factor_t, CutData *cut, CutDataBuilder *builder)
bool DecomposeWithImpliedUpperBound(const CutTerm &term, IntegerValue factor_t, CutTerm &bool_term, CutTerm &slack_term)
~IntegerRoundingCutHelper()
bool ComputeCut(RoundingOptions options, const CutData &base_ct, ImpliedBoundsProcessor *ib_processor=nullptr)
Returns true on success. The cut can be accessed via cut().
const CutData & cut() const
If successful, info about the last generated cut.
std::string Info() const
Single line of text that we append to the cut log line.
void SetSharedStatistics(SharedStatistics *stats)
Simple class to add statistics by name and print them at the end.
Utility class for the AllDiff cut generator.
IntegerValue GetBestLowerBound(std::string &suffix)
void Add(const AffineExpression &expr, int num_expr, const IntegerTrail &integer_trail)
IntegerValue SumOfDifferentMins()
IntegerValue SumOfMinDomainValues()
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
CutGenerator CreateCliqueCutGenerator(const std::vector< IntegerVariable > &base_variables, Model *model)
IntegerValue GetFactorT(IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue max_magnitude)
bool BuildMaxAffineUpConstraint(const LinearExpression &target, IntegerVariable var, const std::vector< std::pair< IntegerValue, IntegerValue > > &affines, Model *model, LinearConstraintBuilder *builder)
CutGenerator CreatePositiveMultiplicationCutGenerator(AffineExpression z, AffineExpression x, AffineExpression y, int linearization_level, Model *model)
A cut generator for z = x * y (x and y >= 0).
LinearConstraint ComputeHyperplanBelowSquare(AffineExpression x, AffineExpression square, IntegerValue x_value, Model *model)
CutGenerator CreateLinMaxCutGenerator(const IntegerVariable target, const std::vector< LinearExpression > &exprs, const std::vector< IntegerVariable > &z_vars, Model *model)
const IntegerVariable kNoIntegerVariable(-1)
std::function< IntegerValue(IntegerValue)> GetSuperAdditiveStrengtheningFunction(IntegerValue positive_rhs, IntegerValue min_magnitude)
CutGenerator CreateSquareCutGenerator(AffineExpression y, AffineExpression x, int linearization_level, Model *model)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
CutGenerator CreateMaxAffineCutGenerator(LinearExpression target, IntegerVariable var, std::vector< std::pair< IntegerValue, IntegerValue > > affines, const std::string cut_name, Model *model)
LinearConstraint ComputeHyperplanAboveSquare(AffineExpression x, AffineExpression square, IntegerValue x_lb, IntegerValue x_ub, Model *model)
CutGenerator CreateAllDifferentCutGenerator(const std::vector< AffineExpression > &exprs, Model *model)
std::function< IntegerValue(IntegerValue)> ExtendNegativeFunction(std::function< IntegerValue(IntegerValue)> base_f, IntegerValue period)
std::function< IntegerValue(IntegerValue)> GetSuperAdditiveStrengtheningMirFunction(IntegerValue positive_rhs, IntegerValue scaling)
std::function< IntegerValue(IntegerValue)> GetSuperAdditiveRoundingFunction(IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue t, IntegerValue max_scaling)
In SWIG mode, we don't want anything besides these top-level includes.
static int input(yyscan_t yyscanner)
std::vector< double > lower_bounds
std::vector< double > upper_bounds
std::optional< int64_t > end
Our cut are always of the form linear_expression <= rhs.
void Canonicalize()
This sorts terms and fill both num_relevant_entries and max_magnitude.
bool FillFromLinearConstraint(const LinearConstraint &base_ct, const util_intops::StrongVector< IntegerVariable, double > &lp_values, IntegerTrail *integer_trail)
bool AllCoefficientsArePositive() const
These functions transform the cut by complementation.
std::vector< CutTerm > terms
bool FillFromParallelVectors(IntegerValue ub, absl::Span< const IntegerVariable > vars, absl::Span< const IntegerValue > coeffs, absl::Span< const double > lp_values, absl::Span< const IntegerValue > lower_bounds, absl::Span< const IntegerValue > upper_bounds)
double ComputeEfficacy() const
void ComplementForPositiveCoefficients()
std::string DebugString() const
double ComputeViolation() const
Computes and returns the cut violation.
IntegerValue max_magnitude
bool AppendOneTerm(IntegerVariable var, IntegerValue coeff, double lp_value, IntegerValue lb, IntegerValue ub)
void ComplementForSmallerLpValues()
std::vector< IntegerVariable > vars
bool only_run_at_level_zero
std::function< bool(LinearConstraintManager *manager)> generate_cuts
IntegerVariable GetUnderlyingLiteralOrNone() const
std::string DebugString() const
int cached_implied_lb
Refer to cached_data_ in ImpliedBoundsProcessor.
double LpDistToMaxValue() const
void ReplaceExpressionByLiteral(IntegerVariable var)
void Complement(absl::int128 *rhs)
std::array< IntegerVariable, 2 > expr_vars
std::array< IntegerValue, 2 > expr_coeffs
bool HasRelevantLpValue() const
std::string DebugString() const
double SlackLpValue(IntegerValue lb) const
IntegerValue implied_bound
bool use_ib_before_heuristic