OR-Tools  9.3
cuts.h
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_SAT_CUTS_H_
15#define OR_TOOLS_SAT_CUTS_H_
16
17#include <functional>
18#include <limits>
19#include <string>
20#include <utility>
21#include <vector>
22
23#include "absl/container/flat_hash_map.h"
24#include "absl/container/flat_hash_set.h"
25#include "absl/strings/str_cat.h"
26#include "absl/types/span.h"
29#include "ortools/sat/integer.h"
32#include "ortools/sat/model.h"
35
36namespace operations_research {
37namespace sat {
38
39// A "cut" generator on a set of IntegerVariable.
40//
41// The generate_cuts() function will usually be called with the current LP
42// optimal solution (but should work for any lp_values). Note that a
43// CutGenerator should:
44// - Only look at the lp_values positions that corresponds to its 'vars' or
45// their negation.
46// - Only add cuts in term of the same variables or their negation.
48 std::vector<IntegerVariable> vars;
49 std::function<bool(
53};
54
55// Given an upper-bounded linear relation (sum terms <= ub), this algorithm
56// inspects the integer variable appearing in the sum and try to replace each of
57// them by a tight lower bound (>= coeff * binary + lb) using the implied bound
58// repository. By tight, we mean that it will take the same value under the
59// current LP solution.
60//
61// We use a class to reuse memory of the tmp terms.
63 public:
64 // We will only replace IntegerVariable appearing in lp_vars_.
65 ImpliedBoundsProcessor(absl::Span<const IntegerVariable> lp_vars_,
66 IntegerTrail* integer_trail,
67 ImpliedBounds* implied_bounds)
68 : lp_vars_(lp_vars_.begin(), lp_vars_.end()),
69 integer_trail_(integer_trail),
70 implied_bounds_(implied_bounds) {}
71
72 // See if some of the implied bounds equation are violated and add them to
73 // the IB cut pool if it is the case.
74 //
75 // Important: This must be called before we process any constraints with a
76 // different lp_values or level zero bounds.
79
80 // Processes and updates the given cut.
83 LinearConstraint* cut);
84
85 // Same as ProcessUpperBoundedConstraint() but instead of just using
86 // var >= coeff * binary + lb we use var == slack + coeff * binary + lb where
87 // slack is a new temporary variable that we create.
88 //
89 // The new slack will be such that slack_infos[(slack - first_slack) / 2]
90 // contains its definition so that we can properly handle it in the cut
91 // generation and substitute it back later.
92 struct SlackInfo {
93 // This slack is equal to sum of terms + offset.
94 std::vector<std::pair<IntegerVariable, IntegerValue>> terms;
95 IntegerValue offset;
96
97 // The slack bounds and current lp_value.
98 IntegerValue lb = IntegerValue(0);
99 IntegerValue ub = IntegerValue(0);
100 double lp_value = 0.0;
101 };
103 bool substitute_only_inner_variables, IntegerVariable first_slack,
105 LinearConstraint* cut, std::vector<SlackInfo>* slack_infos);
106
107 // Only used for debugging.
108 //
109 // Substituting back the slack created by the function above should give
110 // exactly the same cut as the original one.
111 bool DebugSlack(IntegerVariable first_slack,
112 const LinearConstraint& initial_cut,
113 const LinearConstraint& cut,
114 const std::vector<SlackInfo>& info);
115
116 // Add a new variable that could be used in the new cuts.
117 // Note that the cache must be computed to take this into account.
118 void AddLpVariable(IntegerVariable var) { lp_vars_.insert(var); }
119
120 // Once RecomputeCacheAndSeparateSomeImpliedBoundCuts() has been called,
121 // we can get the best implied bound for each variables.
123 double bool_lp_value = 0.0;
124 double slack_lp_value = std::numeric_limits<double>::infinity();
126 IntegerValue bound_diff;
127 IntegerVariable bool_var = kNoIntegerVariable;
128 };
130
131 // As we compute the best implied bounds for each variable, we add violated
132 // cuts here.
133 TopNCuts& IbCutPool() { return ib_cut_pool_; }
134
135 private:
136 BestImpliedBoundInfo ComputeBestImpliedBound(
137 IntegerVariable var,
139
140 absl::flat_hash_set<IntegerVariable> lp_vars_;
141 mutable absl::flat_hash_map<IntegerVariable, BestImpliedBoundInfo> cache_;
142
143 TopNCuts ib_cut_pool_ = TopNCuts(50);
144
145 // Data from the constructor.
146 IntegerTrail* integer_trail_;
147 ImpliedBounds* implied_bounds_;
148
149 // Temporary memory used by ProcessUpperBoundedConstraint().
150 mutable std::vector<std::pair<IntegerVariable, IntegerValue>> tmp_terms_;
151};
152
153// Visible for testing. Returns a function f on integers such that:
154// - f is non-decreasing.
155// - f is super-additive: f(a) + f(b) <= f(a + b)
156// - 1 <= f(divisor) <= max_scaling
157// - For all x, f(x * divisor) = x * f(divisor)
158// - For all x, f(x * divisor + remainder) = x * f(divisor)
159//
160// Preconditions:
161// - 0 <= remainder < divisor.
162// - 1 <= max_scaling.
163//
164// This is used in IntegerRoundingCut() and is responsible for "strengthening"
165// the cut. Just taking f(x) = x / divisor result in the non-strengthened cut
166// and using any function that stricly dominate this one is better.
167//
168// Algorithm:
169// - We first scale by a factor t so that rhs_remainder >= divisor / 2.
170// - Then, if max_scaling == 2, we use the function described
171// in "Strenghtening Chvatal-Gomory cuts and Gomory fractional cuts", Adam N.
172// Letchfrod, Andrea Lodi.
173// - Otherwise, we use a generalization of this which is a discretized version
174// of the classical MIR rounding function that only take the value of the
175// form "an_integer / max_scaling". As max_scaling goes to infinity, this
176// converge to the real-valued MIR function.
177//
178// Note that for each value of max_scaling we will get a different function.
179// And that there is no dominance relation between any of these functions. So
180// it could be nice to try to generate a cut using different values of
181// max_scaling.
182IntegerValue GetFactorT(IntegerValue rhs_remainder, IntegerValue divisor,
183 IntegerValue max_t);
184std::function<IntegerValue(IntegerValue)> GetSuperAdditiveRoundingFunction(
185 IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue t,
186 IntegerValue max_scaling);
187
188// Given an upper bounded linear constraint, this function tries to transform it
189// to a valid cut that violate the given LP solution using integer rounding.
190// Note that the returned cut might not always violate the LP solution, in which
191// case it can be discarded.
192//
193// What this does is basically take the integer division of the constraint by an
194// integer. If the coefficients where doubles, this would be the same as scaling
195// the constraint and then rounding. We choose the coefficient of the most
196// fractional variable (rescaled by its coefficient) as the divisor, but there
197// are other possible alternatives.
198//
199// Note that if the constraint is tight under the given lp solution, and if
200// there is a unique variable not at one of its bounds and fractional, then we
201// are guaranteed to generate a cut that violate the current LP solution. This
202// should be the case for Chvatal-Gomory base constraints modulo our loss of
203// precision while doing exact integer computations.
204//
205// Precondition:
206// - We assumes that the given initial constraint is tight using the given lp
207// values. This could be relaxed, but for now it should always be the case, so
208// we log a message and abort if not, to ease debugging.
209// - The IntegerVariable of the cuts are not used here. We assumes that the
210// first three vectors are in one to one correspondence with the initial order
211// of the variable in the cut.
212//
213// TODO(user): There is a bunch of heuristic involved here, and we could spend
214// more effort tunning them. In particular, one can try many heuristics and keep
215// the best looking cut (or more than one). This is not on the critical code
216// path, so we can spend more effort in finding good cuts.
218 IntegerValue max_scaling = IntegerValue(60);
219};
221 public:
222 void ComputeCut(RoundingOptions options, const std::vector<double>& lp_values,
223 const std::vector<IntegerValue>& lower_bounds,
224 const std::vector<IntegerValue>& upper_bounds,
225 ImpliedBoundsProcessor* ib_processor, LinearConstraint* cut);
226
227 // Returns the number of implied bound lifted Booleans in the last
228 // ComputeCut() call. Useful for investigation.
229 int NumLiftedBooleans() const { return num_lifted_booleans_; }
230
231 private:
232 // The helper is just here to reuse the memory for these vectors.
233 std::vector<int> relevant_indices_;
234 std::vector<double> relevant_lp_values_;
235 std::vector<IntegerValue> relevant_coeffs_;
236 std::vector<IntegerValue> relevant_bound_diffs_;
237 std::vector<IntegerValue> divisors_;
238 std::vector<std::pair<int, IntegerValue>> adjusted_coeffs_;
239 std::vector<IntegerValue> remainders_;
240 std::vector<bool> change_sign_at_postprocessing_;
241 std::vector<IntegerValue> rs_;
242 std::vector<IntegerValue> best_rs_;
243
244 int num_lifted_booleans_ = 0;
245 std::vector<std::pair<IntegerVariable, IntegerValue>> tmp_terms_;
246};
247
248// Helper to find knapsack or flow cover cuts (not yet implemented).
250 public:
251 // Try to find a cut with a knapsack heuristic.
252 // If this returns true, you can get the cut via cut().
253 bool TrySimpleKnapsack(const LinearConstraint base_ct,
254 const std::vector<double>& lp_values,
255 const std::vector<IntegerValue>& lower_bounds,
256 const std::vector<IntegerValue>& upper_bounds);
257
258 // If successful, info about the last generated cut.
259 LinearConstraint* mutable_cut() { return &cut_; }
260 const LinearConstraint& cut() const { return cut_; }
261
262 // Single line of text that we append to the cut log line.
263 const std::string Info() { return absl::StrCat("lift=", num_lifting_); }
264
265 private:
266 struct Term {
267 int index;
268 double dist_to_max_value;
269 IntegerValue positive_coeff; // abs(coeff in original constraint).
270 IntegerValue diff;
271 };
272 std::vector<Term> terms_;
273 std::vector<bool> in_cut_;
274
275 LinearConstraint cut_;
276 int num_lifting_;
277};
278
279// If a variable is away from its upper bound by more than value 1.0, then it
280// cannot be part of a cover that will violate the lp solution. This method
281// returns a reduced constraint by removing such variables from the given
282// constraint.
283LinearConstraint GetPreprocessedLinearConstraint(
284 const LinearConstraint& constraint,
286 const IntegerTrail& integer_trail);
287
288// Returns true if sum of all the variables in the given constraint is less than
289// or equal to constraint upper bound. This method assumes that all the
290// coefficients are non negative.
291bool ConstraintIsTriviallyTrue(const LinearConstraint& constraint,
292 const IntegerTrail& integer_trail);
293
294// If the left variables in lp solution satisfies following inequality, we prove
295// that there does not exist any knapsack cut which is violated by the solution.
296// Let |Cmin| = smallest possible cover size.
297// Let S = smallest (var_ub - lp_values[var]) first |Cmin| variables.
298// Let cut lower bound = sum_(var in S)(var_ub - lp_values[var])
299// For any cover,
300// If cut lower bound >= 1
301// ==> sum_(var in S)(var_ub - lp_values[var]) >= 1
302// ==> sum_(var in cover)(var_ub - lp_values[var]) >= 1
303// ==> The solution already satisfies cover. Since this is true for all covers,
304// this method returns false in such cases.
305// This method assumes that the constraint is preprocessed and has only non
306// negative coefficients.
308 const LinearConstraint& preprocessed_constraint,
310 const IntegerTrail& integer_trail);
311
312// Struct to help compute upper bound for knapsack instance.
314 double profit;
315 double weight;
316 bool operator>(const KnapsackItem& other) const {
317 return profit * other.weight > other.profit * weight;
318 }
319};
320
321// Gets upper bound on profit for knapsack instance by solving the linear
322// relaxation.
323double GetKnapsackUpperBound(std::vector<KnapsackItem> items, double capacity);
324
325// Returns true if the linear relaxation upper bound for the knapsack instance
326// shows that this constraint cannot be used to form a cut. This method assumes
327// that all the coefficients are non negative.
329 const LinearConstraint& constraint,
331 const IntegerTrail& integer_trail);
332
333// Returns true if the given constraint passes all the filters described above.
334// This method assumes that the constraint is preprocessed and has only non
335// negative coefficients.
337 const LinearConstraint& preprocessed_constraint,
339 const IntegerTrail& integer_trail);
340
341// Converts the given constraint into canonical knapsack form (described
342// below) and adds it to 'knapsack_constraints'.
343// Canonical knapsack form:
344// - Constraint has finite upper bound.
345// - All coefficients are positive.
346// For constraint with finite lower bound, this method also adds the negation of
347// the given constraint after converting it to canonical knapsack form.
348void ConvertToKnapsackForm(const LinearConstraint& constraint,
349 std::vector<LinearConstraint>* knapsack_constraints,
350 IntegerTrail* integer_trail);
351
352// Returns true if the cut is lifted. Lifting procedure is described below.
353//
354// First we decide a lifting sequence for the binary variables which are not
355// already in cut. We lift the cut for each lifting candidate one by one.
356//
357// Given the original constraint where the lifting candidate is fixed to one, we
358// compute the maximum value the cut can take and still be feasible using a
359// knapsack problem. We can then lift the variable in the cut using the
360// difference between the cut upper bound and this maximum value.
361bool LiftKnapsackCut(
362 const LinearConstraint& constraint,
364 const std::vector<IntegerValue>& cut_vars_original_coefficients,
365 const IntegerTrail& integer_trail, TimeLimit* time_limit,
366 LinearConstraint* cut);
367
368// A cut generator that creates knpasack cover cuts.
369//
370// For a constraint of type
371// \sum_{i=1..n}(a_i * x_i) <= b
372// where x_i are integer variables with upper bound u_i, a cover of size k is a
373// subset C of {1 , .. , n} such that \sum_{c \in C}(a_c * u_c) > b.
374//
375// A knapsack cover cut is a constraint of the form
376// \sum_{c \in C}(u_c - x_c) >= 1
377// which is equivalent to \sum_{c \in C}(x_c) <= \sum_{c \in C}(u_c) - 1.
378// In other words, in a feasible solution, at least some of the variables do
379// not take their maximum value.
380//
381// If all x_i are binary variables then the cover cut becomes
382// \sum_{c \in C}(x_c) <= |C| - 1.
383//
384// The major difficulty for generating Knapsack cover cuts is finding a minimal
385// cover set C that cut a given floating point solution. There are many ways to
386// heuristically generate the cover but the following method that uses a
387// solution of the LP relaxation of the constraint works the best.
388//
389// Look at a given linear relaxation solution for the integer problem x'
390// and try to solve the following knapsack problem:
391// Minimize \sum_{i=1..n}(z_i * (u_i - x_i')),
392// such that \sum_{i=1..n}(a_i * u_i * z_i) > b,
393// where z_i is a binary decision variable and x_i' are values of the variables
394// in the given relaxation solution x'. If the objective of the optimal solution
395// of this problem is less than 1, this algorithm does not generate any cuts.
396// Otherwise, it adds a knapsack cover cut in the form
397// \sum_{i=1..n}(z_i' * x_i) <= cb,
398// where z_i' is the value of z_i in the optimal solution of the above
399// problem and cb is the upper bound for the cut constraint. Note that the above
400// problem can be converted into a standard kanpsack form by replacing z_i by 1
401// - y_i. In that case the problem becomes
402// Maximize \sum_{i=1..n}((u_i - x_i') * (y_i - 1)),
403// such that
404// \sum_{i=1..n}(a_i * u_i * y_i) <= \sum_{i=1..n}(a_i * u_i) - b - 1.
405//
406// Solving this knapsack instance would help us find the smallest cover with
407// maximum LP violation.
408//
409// Cut strengthning:
410// Let lambda = \sum_{c \in C}(a_c * u_c) - b and max_coeff = \max_{c
411// \in C}(a_c), then cut can be strengthened as
412// \sum_{c \in C}(u_c - x_c) >= ceil(lambda / max_coeff)
413//
414// For further information about knapsack cover cuts see
415// A. Atamtürk, Cover and Pack Inequalities for (Mixed) Integer Programming
416// Annals of Operations Research Volume 139, Issue 1 , pp 21-38, 2005.
417// TODO(user): Implement cut lifting.
419 const std::vector<LinearConstraint>& base_constraints,
420 const std::vector<IntegerVariable>& vars, Model* model);
421
422// A cut generator for z = x * y (x and y >= 0).
423CutGenerator CreatePositiveMultiplicationCutGenerator(AffineExpression z,
424 AffineExpression x,
425 AffineExpression y,
426 int linearization_level,
427 Model* model);
428
429// A cut generator for y = x ^ 2 (x >= 0).
430// It will dynamically add a linear inequality to push y closer to the parabola.
431CutGenerator CreateSquareCutGenerator(AffineExpression y, AffineExpression x,
432 int linearization_level, Model* model);
433
434// A cut generator for all_diff(xi). Let the united domain of all xi be D. Sum
435// of any k-sized subset of xi need to be greater or equal to the sum of
436// smallest k values in D and lesser or equal to the sum of largest k values in
437// D. The cut generator first sorts the variables based on LP values and adds
438// cuts of the form described above if they are violated by lp solution. Note
439// that all the fixed variables are ignored while generating cuts.
441 const std::vector<AffineExpression>& exprs, Model* model);
442
443// Consider the Lin Max constraint with d expressions and n variables in the
444// form: target = max {exprs[k] = Sum (wki * xi + bk)}. k in {1,..,d}.
445// Li = lower bound of xi
446// Ui = upper bound of xi.
447// Let zk be in {0,1} for all k in {1,..,d}.
448// The target = exprs[k] when zk = 1.
449//
450// The following is a valid linearization for Lin Max.
451// target >= exprs[k], for all k in {1,..,d}
452// target <= Sum (wli * xi) + Sum((Nlk + bk) * zk), for all l in {1,..,d}
453// Where Nlk is a large number defined as:
454// Nlk = Sum (max((wki - wli)*Li, (wki - wli)*Ui))
455// = Sum (max corner difference for variable i, target expr l, max expr k)
456//
457// Consider a partition of variables xi into set {1,..,d} as I.
458// i.e. I(i) = j means xi is mapped to jth index.
459// The following inequality is valid and sharp cut for the lin max constraint
460// described above.
461//
462// target <= Sum(i=1..n)(wI(i)i * xi + Sum(k=1..d)(MPlusCoefficient_ki * zk))
463// + Sum(k=1..d)(bk * zk) ,
464// Where MPlusCoefficient_ki = max((wki - wI(i)i) * Li,
465// (wki - wI(i)i) * Ui)
466// = max corner difference for variable i,
467// target expr I(i), max expr k.
468//
469// For detailed proof of validity, refer
470// Reference: "Strong mixed-integer programming formulations for trained neural
471// networks" by Ross Anderson et. (https://arxiv.org/pdf/1811.01988.pdf).
472//
473// In the cut generator, we compute the most violated partition I by computing
474// the rhs value (wI(i)i * lp_value(xi) + Sum(k=1..d)(MPlusCoefficient_ki * zk))
475// for each variable for each partition index. We choose the partition index
476// that gives lowest rhs value for a given variable.
477//
478// Note: This cut generator requires all expressions to contain only positive
479// vars.
480CutGenerator CreateLinMaxCutGenerator(
481 const IntegerVariable target, const std::vector<LinearExpression>& exprs,
482 const std::vector<IntegerVariable>& z_vars, Model* model);
483
484// Helper for the affine max constraint.
485LinearConstraint BuildMaxAffineUpConstraint(
486 const LinearExpression& target, IntegerVariable var,
487 const std::vector<std::pair<IntegerValue, IntegerValue>>& affines,
488 Model* model);
489
490// By definition, the Max of affine functions is convex. The linear polytope is
491// bounded by all affine functions on the bottom, and by a single hyperplane
492// that join the two points at the extreme of the var domain, and their y-values
493// of the max of the affine functions.
494CutGenerator CreateMaxAffineCutGenerator(
495 LinearExpression target, IntegerVariable var,
496 std::vector<std::pair<IntegerValue, IntegerValue>> affines,
497 const std::string cut_name, Model* model);
498
499// Extracts the variables that have a Literal view from base variables and
500// create a generator that will returns constraint of the form "at_most_one"
501// between such literals.
502CutGenerator CreateCliqueCutGenerator(
503 const std::vector<IntegerVariable>& base_variables, Model* model);
504
505} // namespace sat
506} // namespace operations_research
507
508#endif // OR_TOOLS_SAT_CUTS_H_
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
const LinearConstraint & cut() const
Definition: cuts.h:260
LinearConstraint * mutable_cut()
Definition: cuts.h:259
bool TrySimpleKnapsack(const LinearConstraint base_ct, const std::vector< double > &lp_values, const std::vector< IntegerValue > &lower_bounds, const std::vector< IntegerValue > &upper_bounds)
Definition: cuts.cc:1185
void AddLpVariable(IntegerVariable var)
Definition: cuts.h:118
void ProcessUpperBoundedConstraintWithSlackCreation(bool substitute_only_inner_variables, IntegerVariable first_slack, const absl::StrongVector< IntegerVariable, double > &lp_values, LinearConstraint *cut, std::vector< SlackInfo > *slack_infos)
Definition: cuts.cc:1613
void ProcessUpperBoundedConstraint(const absl::StrongVector< IntegerVariable, double > &lp_values, LinearConstraint *cut)
Definition: cuts.cc:1520
bool DebugSlack(IntegerVariable first_slack, const LinearConstraint &initial_cut, const LinearConstraint &cut, const std::vector< SlackInfo > &info)
Definition: cuts.cc:1746
void RecomputeCacheAndSeparateSomeImpliedBoundCuts(const absl::StrongVector< IntegerVariable, double > &lp_values)
Definition: cuts.cc:1603
BestImpliedBoundInfo GetCachedImpliedBoundInfo(IntegerVariable var)
Definition: cuts.cc:1529
ImpliedBoundsProcessor(absl::Span< const IntegerVariable > lp_vars_, IntegerTrail *integer_trail, ImpliedBounds *implied_bounds)
Definition: cuts.h:65
void ComputeCut(RoundingOptions options, const std::vector< double > &lp_values, const std::vector< IntegerValue > &lower_bounds, const std::vector< IntegerValue > &upper_bounds, ImpliedBoundsProcessor *ib_processor, LinearConstraint *cut)
Definition: cuts.cc:731
ModelSharedTimeLimit * time_limit
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
int index
void ConvertToKnapsackForm(const LinearConstraint &constraint, std::vector< LinearConstraint > *knapsack_constraints, IntegerTrail *integer_trail)
Definition: cuts.cc:404
LinearConstraint GetPreprocessedLinearConstraint(const LinearConstraint &constraint, const absl::StrongVector< IntegerVariable, double > &lp_values, const IntegerTrail &integer_trail)
Definition: cuts.cc:266
CutGenerator CreateAllDifferentCutGenerator(const std::vector< AffineExpression > &exprs, Model *model)
Definition: cuts.cc:1876
bool CanFormValidKnapsackCover(const LinearConstraint &preprocessed_constraint, const absl::StrongVector< IntegerVariable, double > &lp_values, const IntegerTrail &integer_trail)
Definition: cuts.cc:386
IntegerValue GetFactorT(IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue max_t)
Definition: cuts.cc:635
double GetKnapsackUpperBound(std::vector< KnapsackItem > items, const double capacity)
Definition: cuts.cc:334
bool CanBeFilteredUsingCutLowerBound(const LinearConstraint &preprocessed_constraint, const absl::StrongVector< IntegerVariable, double > &lp_values, const IntegerTrail &integer_trail)
Definition: cuts.cc:306
const IntegerVariable kNoIntegerVariable(-1)
CutGenerator CreateLinMaxCutGenerator(const IntegerVariable target, const std::vector< LinearExpression > &exprs, const std::vector< IntegerVariable > &z_vars, Model *model)
Definition: cuts.cc:1985
CutGenerator CreatePositiveMultiplicationCutGenerator(AffineExpression z, AffineExpression x, AffineExpression y, int linearization_level, Model *model)
Definition: cuts.cc:1358
LinearConstraint BuildMaxAffineUpConstraint(const LinearExpression &target, IntegerVariable var, const std::vector< std::pair< IntegerValue, IntegerValue > > &affines, Model *model)
Definition: cuts.cc:2069
bool CanBeFilteredUsingKnapsackUpperBound(const LinearConstraint &constraint, const absl::StrongVector< IntegerVariable, double > &lp_values, const IntegerTrail &integer_trail)
Definition: cuts.cc:352
std::function< IntegerValue(IntegerValue)> GetSuperAdditiveRoundingFunction(IntegerValue rhs_remainder, IntegerValue divisor, IntegerValue t, IntegerValue max_scaling)
Definition: cuts.cc:643
CutGenerator CreateSquareCutGenerator(AffineExpression y, AffineExpression x, int linearization_level, Model *model)
Definition: cuts.cc:1452
CutGenerator CreateMaxAffineCutGenerator(LinearExpression target, IntegerVariable var, std::vector< std::pair< IntegerValue, IntegerValue > > affines, const std::string cut_name, Model *model)
Definition: cuts.cc:2105
CutGenerator CreateKnapsackCoverCutGenerator(const std::vector< LinearConstraint > &base_constraints, const std::vector< IntegerVariable > &vars, Model *model)
Definition: cuts.cc:454
bool ConstraintIsTriviallyTrue(const LinearConstraint &constraint, const IntegerTrail &integer_trail)
Definition: cuts.cc:290
bool LiftKnapsackCut(const LinearConstraint &constraint, const absl::StrongVector< IntegerVariable, double > &lp_values, const std::vector< IntegerValue > &cut_vars_original_coefficients, const IntegerTrail &integer_trail, TimeLimit *time_limit, LinearConstraint *cut)
Definition: cuts.cc:187
CutGenerator CreateCliqueCutGenerator(const std::vector< IntegerVariable > &base_variables, Model *model)
Definition: cuts.cc:2127
Collection of objects used to extend the Constraint Solver library.
int64_t capacity
std::vector< double > lower_bounds
std::vector< double > upper_bounds
std::optional< int64_t > end
std::vector< IntegerVariable > vars
Definition: cuts.h:48
std::function< bool(const absl::StrongVector< IntegerVariable, double > &lp_values, LinearConstraintManager *manager)> generate_cuts
Definition: cuts.h:52
std::vector< std::pair< IntegerVariable, IntegerValue > > terms
Definition: cuts.h:94
bool operator>(const KnapsackItem &other) const
Definition: cuts.h:316