OR-Tools  8.0
linear_constraint_manager.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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_LINEAR_CONSTRAINT_MANAGER_H_
15 #define OR_TOOLS_SAT_LINEAR_CONSTRAINT_MANAGER_H_
16 
17 #include <cstddef>
18 #include <vector>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/container/flat_hash_set.h"
24 #include "ortools/sat/model.h"
27 
28 namespace operations_research {
29 namespace sat {
30 
31 // This class holds a list of globally valid linear constraints and has some
32 // logic to decide which one should be part of the LP relaxation. We want more
33 // for a better relaxation, but for efficiency we do not want to have too much
34 // constraints while solving the LP.
35 //
36 // This class is meant to contain all the initial constraints of the LP
37 // relaxation and to get new cuts as they are generated. Thus, it can both
38 // manage cuts but also only add the initial constraints lazily if there is too
39 // many of them.
41  public:
42  struct ConstraintInfo {
44  double l2_norm = 0.0;
46  double objective_parallelism = 0.0;
48  bool is_in_lp = false;
49  size_t hash;
50  double current_score = 0.0;
51 
52  // Updated only for deletable constraints. This is incremented every time
53  // ChangeLp() is called and the constraint is active in the LP or not in the
54  // LP and violated.
55  double active_count = 0.0;
56 
57  // For now, we mark all the generated cuts as deletable and the problem
58  // constraints as undeletable.
59  // TODO(user): We can have a better heuristics. Some generated good cuts
60  // can be marked undeletable and some unused problem specified constraints
61  // can be marked deletable.
62  bool is_deletable = false;
63  };
64 
66  : sat_parameters_(*model->GetOrCreate<SatParameters>()),
67  integer_trail_(*model->GetOrCreate<IntegerTrail>()),
68  time_limit_(model->GetOrCreate<TimeLimit>()),
69  model_(model) {}
71 
72  // Add a new constraint to the manager. Note that we canonicalize constraints
73  // and merge the bounds of constraints with the same terms. We also perform
74  // basic preprocessing. If added is given, it will be set to true if this
75  // constraint was actually a new one and to false if it was dominated by an
76  // already existing one.
77  DEFINE_INT_TYPE(ConstraintIndex, int32);
78  ConstraintIndex Add(LinearConstraint ct, bool* added = nullptr);
79 
80  // Same as Add(), but logs some information about the newly added constraint.
81  // Cuts are also handled slightly differently than normal constraints.
82  //
83  // Returns true if a new cut was added and false if this cut is not
84  // efficacious or if it is a duplicate of an already existing one.
85  bool AddCut(LinearConstraint ct, std::string type_name,
86  const gtl::ITIVector<IntegerVariable, double>& lp_solution,
87  std::string extra_info = "");
88 
89  // The objective is used as one of the criterion to score cuts.
90  // The more a cut is parallel to the objective, the better its score is.
91  void SetObjectiveCoefficient(IntegerVariable var, IntegerValue coeff);
92 
93  // Heuristic to decides what LP is best solved next. The given lp_solution
94  // should usually be the optimal solution of the LP returned by GetLp() before
95  // this call, but is just used as an heuristic.
96  //
97  // The current solution state is used for detecting inactive constraints. It
98  // is also updated correctly on constraint deletion/addition so that the
99  // simplex can be fully iterative on restart by loading this modified state.
100  //
101  // Returns true iff LpConstraints() will return a different LP than before.
102  bool ChangeLp(const gtl::ITIVector<IntegerVariable, double>& lp_solution,
103  glop::BasisState* solution_state);
104 
105  // This can be called initially to add all the current constraint to the LP
106  // returned by GetLp().
107  void AddAllConstraintsToLp();
108 
109  // All the constraints managed by this class.
111  const {
112  return constraint_infos_;
113  }
114 
115  // The set of constraints indices in AllConstraints() that should be part
116  // of the next LP to solve.
117  const std::vector<ConstraintIndex>& LpConstraints() const {
118  return lp_constraints_;
119  }
120 
121  int64 num_cuts() const { return num_cuts_; }
122  int64 num_shortened_constraints() const { return num_shortened_constraints_; }
123  int64 num_coeff_strenghtening() const { return num_coeff_strenghtening_; }
124 
125  // If a debug solution has been loaded, this checks if the given constaint cut
126  // it or not. Returns true iff everything is fine and the cut does not violate
127  // the loaded solution.
128  bool DebugCheckConstraint(const LinearConstraint& cut);
129 
130  private:
131  // Heuristic that decide which constraints we should remove from the current
132  // LP. Note that such constraints can be added back later by the heuristic
133  // responsible for adding new constraints from the pool.
134  //
135  // Returns true iff one or more constraints where removed.
136  //
137  // If the solutions_state is empty, then this function does nothing and
138  // returns false (this is used for tests). Otherwise, the solutions_state is
139  // assumed to correspond to the current LP and to be of the correct size.
140  bool MaybeRemoveSomeInactiveConstraints(glop::BasisState* solution_state);
141 
142  // Apply basic inprocessing simplification rules:
143  // - remove fixed variable
144  // - reduce large coefficient (i.e. coeff strenghtenning or big-M reduction).
145  // This uses level-zero bounds.
146  // Returns true if the terms of the constraint changed.
147  bool SimplifyConstraint(LinearConstraint* ct);
148 
149  // Helper method to compute objective parallelism for a given constraint. This
150  // also lazily computes objective norm.
151  void ComputeObjectiveParallelism(const ConstraintIndex ct_index);
152 
153  // Multiplies all active counts and the increment counter by the given
154  // 'scaling_factor'. This should be called when at least one of the active
155  // counts is too high.
156  void RescaleActiveCounts(double scaling_factor);
157 
158  // Removes some deletable constraints with low active counts. For now, we
159  // don't remove any constraints which are already in LP.
160  void PermanentlyRemoveSomeConstraints();
161 
162  const SatParameters& sat_parameters_;
163  const IntegerTrail& integer_trail_;
164 
165  // Set at true by Add()/SimplifyConstraint() and at false by ChangeLp().
166  bool current_lp_is_changed_ = false;
167 
168  // Optimization to avoid calling SimplifyConstraint() when not needed.
169  int64 last_simplification_timestamp_ = 0;
170 
172 
173  // The subset of constraints currently in the lp.
174  std::vector<ConstraintIndex> lp_constraints_;
175 
176  // We keep a map from the hash of our constraint terms to their position in
177  // constraints_. This is an optimization to detect duplicate constraints. We
178  // are robust to collisions because we always relies on the ground truth
179  // contained in constraints_ and the code is still okay if we do not merge the
180  // constraints.
181  absl::flat_hash_map<size_t, ConstraintIndex> equiv_constraints_;
182 
183  int64 num_merged_constraints_ = 0;
184  int64 num_shortened_constraints_ = 0;
185  int64 num_splitted_constraints_ = 0;
186  int64 num_coeff_strenghtening_ = 0;
187 
188  int64 num_cuts_ = 0;
189  std::map<std::string, int> type_to_num_cuts_;
190 
191  bool objective_is_defined_ = false;
192  bool objective_norm_computed_ = false;
193  double objective_l2_norm_ = 0.0;
194 
195  // Dense representation of the objective coeffs indexed by positive variables
196  // indices. It contains 0.0 where the variables does not appear in the
197  // objective.
198  gtl::ITIVector<IntegerVariable, double> dense_objective_coeffs_;
199 
200  TimeLimit* time_limit_;
201  Model* model_;
202 
203  // We want to decay the active counts of all constraints at each call and
204  // increase the active counts of active/violated constraints. However this can
205  // be too slow in practice. So instead, we keep an increment counter and
206  // update only the active/violated constraints. The counter itself is
207  // increased by a factor at each call. This has the same effect as decaying
208  // all the active counts at each call. This trick is similar to sat clause
209  // management.
210  double constraint_active_count_increase_ = 1.0;
211 
212  int32 num_deletable_constraints_ = 0;
213 };
214 
215 } // namespace sat
216 } // namespace operations_research
217 
218 #endif // OR_TOOLS_SAT_LINEAR_CONSTRAINT_MANAGER_H_
operations_research::sat::LinearConstraintManager::LinearConstraintManager
LinearConstraintManager(Model *model)
Definition: linear_constraint_manager.h:65
operations_research::sat::LinearConstraintManager::num_coeff_strenghtening
int64 num_coeff_strenghtening() const
Definition: linear_constraint_manager.h:123
var
IntVar * var
Definition: expr_array.cc:1858
time_limit.h
linear_constraint.h
operations_research::sat::LinearConstraintManager::num_shortened_constraints
int64 num_shortened_constraints() const
Definition: linear_constraint_manager.h:122
operations_research::sat::LinearConstraintManager::AddCut
bool AddCut(LinearConstraint ct, std::string type_name, const gtl::ITIVector< IntegerVariable, double > &lp_solution, std::string extra_info="")
Definition: linear_constraint_manager.cc:204
model.h
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::sat::LinearConstraintManager::ConstraintInfo::hash
size_t hash
Definition: linear_constraint_manager.h:49
operations_research::sat::LinearConstraintManager::ChangeLp
bool ChangeLp(const gtl::ITIVector< IntegerVariable, double > &lp_solution, glop::BasisState *solution_state)
Definition: linear_constraint_manager.cc:437
operations_research::sat::LinearConstraintManager::ConstraintInfo::is_in_lp
bool is_in_lp
Definition: linear_constraint_manager.h:48
operations_research::sat::IntegerTrail
Definition: integer.h:534
int64
int64_t int64
Definition: integral_types.h:34
operations_research::sat::LinearConstraintManager::ConstraintInfo::inactive_count
int64 inactive_count
Definition: linear_constraint_manager.h:45
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
int32
int int32
Definition: integral_types.h:33
revised_simplex.h
operations_research::glop::BasisState
Definition: revised_simplex.h:132
operations_research::sat::LinearConstraintManager::Add
ConstraintIndex Add(LinearConstraint ct, bool *added=nullptr)
Definition: linear_constraint_manager.cc:122
operations_research::sat::LinearConstraint
Definition: linear_constraint.h:39
operations_research::sat::LinearConstraintManager::ConstraintInfo::constraint
LinearConstraint constraint
Definition: linear_constraint_manager.h:43
sat_parameters.pb.h
operations_research::sat::LinearConstraintManager::DEFINE_INT_TYPE
DEFINE_INT_TYPE(ConstraintIndex, int32)
operations_research::TimeLimit
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
operations_research::sat::LinearConstraintManager::ConstraintInfo::current_score
double current_score
Definition: linear_constraint_manager.h:50
ct
const Constraint * ct
Definition: demon_profiler.cc:42
operations_research::sat::LinearConstraintManager::LpConstraints
const std::vector< ConstraintIndex > & LpConstraints() const
Definition: linear_constraint_manager.h:117
operations_research::sat::LinearConstraintManager
Definition: linear_constraint_manager.h:40
model
GRBmodel * model
Definition: gurobi_interface.cc:195
operations_research::sat::LinearConstraintManager::AddAllConstraintsToLp
void AddAllConstraintsToLp()
Definition: linear_constraint_manager.cc:669
operations_research::sat::LinearConstraintManager::ConstraintInfo::objective_parallelism_computed
bool objective_parallelism_computed
Definition: linear_constraint_manager.h:47
operations_research::sat::LinearConstraintManager::ConstraintInfo::objective_parallelism
double objective_parallelism
Definition: linear_constraint_manager.h:46
operations_research::sat::LinearConstraintManager::AllConstraints
const gtl::ITIVector< ConstraintIndex, ConstraintInfo > & AllConstraints() const
Definition: linear_constraint_manager.h:110
operations_research::sat::LinearConstraintManager::ConstraintInfo::l2_norm
double l2_norm
Definition: linear_constraint_manager.h:44
operations_research::sat::LinearConstraintManager::num_cuts
int64 num_cuts() const
Definition: linear_constraint_manager.h:121
operations_research::sat::LinearConstraintManager::ConstraintInfo::is_deletable
bool is_deletable
Definition: linear_constraint_manager.h:62
operations_research::sat::LinearConstraintManager::ConstraintInfo
Definition: linear_constraint_manager.h:42
gtl::ITIVector< IntegerVariable, double >
operations_research::sat::LinearConstraintManager::ConstraintInfo::active_count
double active_count
Definition: linear_constraint_manager.h:55
operations_research::sat::LinearConstraintManager::~LinearConstraintManager
~LinearConstraintManager()
Definition: linear_constraint_manager.cc:45
operations_research::sat::LinearConstraintManager::DebugCheckConstraint
bool DebugCheckConstraint(const LinearConstraint &cut)
Definition: linear_constraint_manager.cc:677
operations_research::sat::LinearConstraintManager::SetObjectiveCoefficient
void SetObjectiveCoefficient(IntegerVariable var, IntegerValue coeff)
Definition: linear_constraint_manager.cc:298