Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
|
Helper to find knapsack cover cuts. More...
#include <cuts.h>
Public Member Functions | |
~CoverCutHelper () | |
bool | TrySimpleKnapsack (const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr) |
bool | TryWithLetchfordSouliLifting (const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr) |
bool | TrySingleNodeFlow (const CutData &input_ct, ImpliedBoundsProcessor *ib_processor=nullptr) |
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) |
void | ClearCache () |
operations_research::sat::CoverCutHelper::~CoverCutHelper | ( | ) |
|
inline |
|
inline |
|
inline |
|
inline |
bool operations_research::sat::CoverCutHelper::TrySimpleKnapsack | ( | const CutData & | input_ct, |
ImpliedBoundsProcessor * | ib_processor = nullptr ) |
Try to find a cut with a knapsack heuristic. This assumes an input with all coefficients positive. If this returns true, you can get the cut via cut().
This uses a lifting procedure similar to what is described in "Lifting the Knapsack Cover Inequalities for the Knapsack Polytope", Adam N. Letchfod, Georgia Souli. In particular the section "Lifting via mixed-integer rounding".
Tricky: This only work because the cut absl128 rhs is not changed by these operations.
We only look at non-Boolean with an lp value not close to the upper bound.
If some implied bound substitution are possible, we do not cache anything currently because the logic is currently sighlty different betweent the two code. Fix?
The cut is just obtained by complementing the variable in the cover and applying the MIR super additive function.
Update counters.
bool operations_research::sat::CoverCutHelper::TrySingleNodeFlow | ( | const CutData & | input_ct, |
ImpliedBoundsProcessor * | ib_processor = nullptr ) |
It turns out that what FlowCoverCutHelper is doing is really just finding a cover and generating a cut via coefficient strenghtening instead of MIR rounding. This more generic version should just always outperform our old code.
After complementing the term in the cover, we have sum -ci.X + other_terms <= -slack;
We do not support complex terms, but we shouldn't get any.
The algorithm goes as follow:
Using implied bound we have two cases (all coeffs positive): 1/ ci.Xi = ci.fi.Bi + ci.Si : always good. 2/ ci.Xi = ci.di.Bi - ci.Si <= di.Bi: good if Si lp_value is zero.
Lifting.
Compute good period. We don't want to extend it in the simpler case where f(x)=-1 if x < 0.
Generate the cut.
bool operations_research::sat::CoverCutHelper::TryWithLetchfordSouliLifting | ( | const CutData & | input_ct, |
ImpliedBoundsProcessor * | ib_processor = nullptr ) |
Applies the lifting procedure described in "On Lifted Cover Inequalities: A New Lifting Procedure with Unusual Properties", Adam N. Letchford, Georgia Souli. This assumes an input with all coefficients positive.
The algo is pretty simple, given a cover C for a given rhs. We compute a rational weight p/q so that sum_C min(w_i, p/q) = rhs. Note that q is pretty small (lower or equal to the size of C). The generated cut is then of the form sum X_i in C for which w_i <= p / q
C
- 1.gamma_i being the smallest k such that w_i <= sum of the k + 1 largest min(w_i, p/q) for i in C. In particular, it is zero if w_i <= p/q.
We already called GetCoverSizeForBooleans() and ib_processor was nullptr, so reuse that info.
Perform IB expansion with no restriction, all coeff should still be positive.
We don't support big rhs here. Note however than since this only deal with Booleans, it is less likely.
Collect the weight in the cover.
Compute the correct threshold so that if we round down larger weights to p/q. We have sum of the weight in cover == base_rhs.
Compute thresholds. For the first q values, thresholds[i] is the smallest integer such that q * threshold[i] > p * (i + 1).
For the other values, we just add the weights.
Generate the cut.
Our algo is quadratic in worst case, but large coefficients should be rare, and in practice we don't really see this.
Find the largest index <= coeff.