Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
zero_half_cuts.h
Go to the documentation of this file.
1// Copyright 2010-2024 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_ZERO_HALF_CUTS_H_
15#define OR_TOOLS_SAT_ZERO_HALF_CUTS_H_
16
17#include <functional>
18#include <utility>
19#include <vector>
20
21#include "absl/types/span.h"
23#include "ortools/sat/integer.h"
24#include "ortools/sat/util.h"
25
26namespace operations_research {
27namespace sat {
28
29// Heuristic to find a good sums of rows from the LP (with coeff -1, +1) that
30// can lead to a violated zero-half cut (i.e. after integer rounding with a
31// divisor 2).
32//
33// For this, all that matter is the parity of the coefficients and the rhs in
34// the linear combination of the original problem constraint. So this class
35// maintain a copy of the LP matrix modulo 2 on which simplification and
36// heuristic are performed to find good cut candidates(s).
37//
38// Most of what is done here is described in the paper "Algorithms to Separate
39// {0, 1/2}-Chvátal-Gomory Cuts", Arie M. C. A. Koster, Adrian Zymolka, Manuel
40// Kutschka.
42 public:
43 // Public API: ProcessVariables() must be called first and then constraints
44 // can be added one by one. Finally GetZeroHalfInterestingCuts() will return a
45 // set of good candidates.
46 //
47 // TODO(user): This is a first implementation, both the heuristic and the
48 // code performance can probably be improved uppon.
49 void ProcessVariables(const std::vector<double>& lp_values,
50 absl::Span<const IntegerValue> lower_bounds,
51 absl::Span<const IntegerValue> upper_bounds);
52 void AddOneConstraint(glop::RowIndex, absl::Span<const glop::ColIndex> cols,
53 absl::Span<const IntegerValue> coeffs, IntegerValue lb,
54 IntegerValue ub);
55 std::vector<std::vector<std::pair<glop::RowIndex, IntegerValue>>>
57
58 // Visible for testing.
59 void Reset(int size);
60
61 // Visible for testing.
62 //
63 // Boolean matrix. Each column correspond to one variable (col indices).
64 // Each row to a sum of the initial problem constraints. We store the
65 // coefficient modulo 2, so only the positions of the ones.
67 // How this row was formed from the initial problem constraints.
68 std::vector<std::pair<glop::RowIndex, IntegerValue>> multipliers;
69
70 // The index of the odd coefficient of this combination.
71 std::vector<int> cols;
72
73 // The parity of the rhs (1 for odd).
75
76 // How tight this constraints is under the current LP solution.
77 double slack;
78 };
79 void AddBinaryRow(const CombinationOfRows& binary_row);
80 const CombinationOfRows& MatrixRow(int row) const { return rows_[row]; }
81 const std::vector<int>& MatrixCol(int col) const { return col_to_rows_[col]; }
82
83 // Visible for testing.
84 //
85 // Adds the given row to all other rows having an odd cofficient on the given
86 // column. This then eliminate the entry (col, row) that is now a singleton by
87 // incresing the slack of the given row.
88 void EliminateVarUsingRow(int col, int row);
89
90 // Visible for testing.
91 //
92 // Like std::set_symmetric_difference, but use a vector<bool> instead of sort.
93 // This assumes tmp_marked_ to be all false. We don't DCHECK it here for
94 // speed, but it DCHECKed on each EliminateVarUsingRow() call.
95 void SymmetricDifference(absl::Span<const int> a, std::vector<int>* b);
96
97 private:
98 // As we combine rows, when the activity of a combination get too far away
99 // from its bound, we just discard it. Note that the row will still be there
100 // but its index will not appear in the col-wise representation of the matrix.
101 const double kSlackThreshold = 0.5;
102 const int kMaxAggregationSize = 100;
103
104 // We don't consider long constraint or constraint with high magnitude, since
105 // the highest violation we can hope for is 1, and if the magnitude is large
106 // then the cut efficacity will not be great.
107 const int kMaxInputConstraintSize = 100;
108 const double kMaxInputConstraintMagnitude = 1e6;
109
110 // Variable information.
111 std::vector<double> lp_values_;
112 std::vector<double> shifted_lp_values_;
113 std::vector<int> bound_parity_;
114
115 // Binary matrix.
116 //
117 // Note that as we combine rows, we never move their indices. So after initial
118 // creation rows_ will always have the same size.
119 std::vector<CombinationOfRows> rows_;
120 std::vector<std::vector<int>> col_to_rows_;
121 std::vector<int> singleton_cols_;
122
123 // Temporary vector used by SymmetricDifference().
124 std::vector<bool> tmp_marked_;
125};
126
127} // namespace sat
128} // namespace operations_research
129
130#endif // OR_TOOLS_SAT_ZERO_HALF_CUTS_H_
IntegerValue size
const CombinationOfRows & MatrixRow(int row) const
void SymmetricDifference(absl::Span< const int > a, std::vector< int > *b)
void Reset(int size)
Visible for testing.
void AddOneConstraint(glop::RowIndex, absl::Span< const glop::ColIndex > cols, absl::Span< const IntegerValue > coeffs, IntegerValue lb, IntegerValue ub)
std::vector< std::vector< std::pair< glop::RowIndex, IntegerValue > > > InterestingCandidates(ModelRandomGenerator *random)
void ProcessVariables(const std::vector< double > &lp_values, absl::Span< const IntegerValue > lower_bounds, absl::Span< const IntegerValue > upper_bounds)
void EliminateVarUsingRow(int col, int row)
This is basically one step of a Gaussian elimination with the given pivot.
const std::vector< int > & MatrixCol(int col) const
void AddBinaryRow(const CombinationOfRows &binary_row)
int64_t a
Definition table.cc:44
ColIndex col
Definition markowitz.cc:187
RowIndex row
Definition markowitz.cc:186
In SWIG mode, we don't want anything besides these top-level includes.
std::vector< double > lower_bounds
Definition lp_utils.cc:746
std::vector< double > upper_bounds
Definition lp_utils.cc:747
double slack
How tight this constraints is under the current LP solution.
std::vector< std::pair< glop::RowIndex, IntegerValue > > multipliers
How this row was formed from the initial problem constraints.
std::vector< int > cols
The index of the odd coefficient of this combination.